I pull in image links from several sources so I have a mix images that render and then have problems rendering.
I have many images that return with http error 400, 403 etc.
Am I able to detect this in the django template so that I can render something more suitable than a broken image?
Something like:
{% if ia.image.url %}
<img src="{{media_url}}{{ia.image.url}}" alt="#" class="trimimg1" />
{% else %}
<img src="{% static 'common/app/images/news-default.jpg' %}" alt="#" class="trimimg1" />
{% endif %}
You are able to detect broken links in the django template or also before in the view. However, depending on the type of project you are doing, I would not recommend this - at least not without caching.
Let's talk about the theory first and then about a possible alternative solution:
If you only are using images that you are hosting yourself, serving the images to your clients should be no problem as long as the files on your server exist. You can easily check that by retrieving the path of the image and checking if the file exists (provided, that you may access the file and did not separate completely the media server, then you have to handle this as if it is external hosting).
If I read your question carefully, you seem to link to images hosted on external servers though. It is possible to handle a few but probably not all problems with those images on the server side. Either you do this while storing the image URL already, or you do a periodical check in the background. If you really want to check every time you are sending the image URL to the user, you might create a heavy load on the server just for checking. In this case, I recommend to rely heavily on caching and to cache the return value of the method for checking the availability of the URL for a certain time.
That being said, you could do the following in your template:
In theory, you could create your own custom filter "urlexists" (See https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/ ). This filter would retrieve the URL you want to check. It would try to retrieve the file from the remote server (Download just the headers, see https://stackoverflow.com/a/16778473/1331407 on how to do that) and return True, if the URL exists and False otherwise.
Usage:
{% if ia.image.url|urlexists %}
<img src="{{media_url}}{{ia.image.url}}" alt="#" class="trimimg1" />
{% else %}
<img src="{% static 'common/app/images/news-default.jpg' %}" alt="#" class="trimimg1" />
{% endif %}
As I said, it is a solution but I do not recommend this.
Alternative solution
I would rather recommend to handle the HTTP error on the client side using JavaScript. That script can be as easy as an and a JavaScript function that then replaces the image src with a placeholder image that you provide.
Examples on how to do that are provided here: Detecting an image 404 in javascript
You could even do one better: If you want to know about the inaccessible image, you could modify the URL of the placeholder image to a view that retrieves the image URL and logs it somewhere in your database so that you can remove the URL from your image database later. The view would always just return the placeholder image.
Why do I recommend handling this error on the client side?
Simple answer: Server load and access rights. Checking all URLs constantly will create a huge server load and traffic, both of which you might not want to handle all the time. In addition, your server might not be allowed to access certain images that you would filter out - or vice versa. Some servers allow you only to access their images after you loaded a page containing those images beforehand (I learned that trying to scrape movie posters from websites for my personal BluRay library index). An image that your server might have scraped from somewhere and that you are able to access might thus not be accessible for your clients webbrowser. Thus he might still see broken images. If you check the availability on your clients browser, he will never see the broken image, since his or her browser is always replacing those with a placeholder. If you include my suggestion above, you would even crowdsource image availability checking, reducing server load on your and foreign servers.
Related
Firstly i'm very much a beginner and learning Django, but I just cannot get Sorl-Thumbnail to work in the Gallery aspects of a photography site I am developing.
The site is in development and DEBUG = True, all installs went well including dependencies as far as I can see. 'sorl.thumbnail', is added to apps and migrations have gone through.
I am using is to generate thumbnail within a template for loop to generate my galleries. But I get broken thumbnails for each image objects. On inspecting i get a tag img tag
<img src="/media/cache/5c/58/5c58ba75425e372e94b739e292690b85.jpg">
All other images work in Admin, and on the rest of the site. I've checked MEDIA_URL but this seems ok. I cannot see a cache folder within my media folder though, does sorl generate one?
I've changed my model so it is using the Sorl-Thumnail imagefield, but this didn'd achieve anything, I have THUMBNAIL_DEBUG = True in setting but this is not giving me anything in terminal.
{% for img in album.images %}
{% thumbnail img "100x100" crop="center" as im %}
<img src="{{ im.url }}">
{% empty %}
Well, I didin't manage to solve this. I 'think' it maybe a permissions problem (I'm using Windows) but I could never get any errors back from sorl-thumbnail so little info to go on. I worked on all the other solutions on SO but I could never get it to create the Cache folder.
I removed the module and used Imagekit in the end which worked like a charm. I'm just annoyed I never got to the bottom of my problem with Sorl.
I am attempting to create a pretty simple website using Django that will have a number of audio files stored in it and available for streaming and downloading. I know that there are other ways to do this, like using AWS, but I wanted to figure this way out first. I'll include my template here but wanted to note that it is currently messy because I have been experimenting with different structures to figure this problem out.
{% for song in concert.song_set.all %}
<li>{{ song.song_title }}</li>
<li>{{ song.song_location }}</li>
<!-- Working -->
<audio
class = "audioPlayer uniqueShowAP"
controls <--controlsList="nodownload"
src="{% static 'shows/audio/redRocks2019/01 Yi.mp3' %}">
Your browser does not support the
<code>audio</code> element.
</audio>
<!-- Not Working...yet -->
<audio
class = "audioPlayer uniqueShowAP"
controls <--controlsList="nodownload"
src="/shows/static/shows/{{ song.song_location }}">
Your browser does not support the
<code>audio</code> element.
</audio>
{% endfor %}
What I want to happen is for every concert that I save it will go through the songs saved under that concert and add them to under the name of the song. I have each song's relative location saved in the data base so that I should be able to just call upon it's location.
I've tested this out by calling {{ song.song_location }} which correctly displays each song's location.
I also tried using src="{% static 'shows/audio/redRocks2019/01 Yi.mp3' %}" just to make sure that the element is at least set up correctly and that works too.
How do I format the src="" in the element to point it to the correct audio files? I can include my views and models or whatever additional information you might need to help me figure this out. I've been at this for a while now and just need someone to point me in the right direction.
I think you should look into using a FileField. You can have a Song model, with a song_file = FileField(upload_to='song_files/') field. Then, the files can be saved and accessed more easily when looping through model instances:
<audio src='{{ song.song_file.url }}' controls></audio>
These files will be stored locally per your media settings. You can easily transition to using a storage solution like S3 for your media files, as you mentioned. It works incredibly smoothly with Django, so don't be scared.
Static files should be for things like css, js, and images that aren't going to change, like a favicon perhaps. I guess it could be used for a static song, hypothetically. But thinking about using static files this way above in conjunction with a model instance is a bit contrived and confusing, I think.
I am part editor and part developer and not utterly advanced at either career. But I am carrying out only a small-scale project. I'm thinking that in the blog that I recently added to my Django site (as yet only on the development server), with Wagtail and Puput, I might want to upload, say, two ~50KB images per week for five years, after which I'll be doing something else. There will never be a huge number of readers or a need for vast storage. Those being the circumstances, I specifically want to know if what I'm doing to overcome the problems that I encountered with uploaded images not resizing to small screens in the Puput blog, non-responsive design, looks feasible. Or, did I make some stupid mistake and, say, just use the Puput/Wagtail editor incorrectly?
When you click into the "body" textbox in the Puput editor to insert an image, it's quite simple. You just browse for your file, give the image a name, and select whether you want full-width or aligned on the left or right. And upon doing that your image will be uploaded into your previously established "media" folder and the database will simply be updated to contain the location of your image in the "media" folder. The <img> tag in your text body will be given an ID attribute which is a link to the database entry.
Two troubling things then happen: (1) when you go into the browser's Responsive Design Mode the image is bigger than the small screen, no responsiveness; and, you actually don't now have an image stored in your media folder, you have three--- the original is in a subdirectory called "original_images" and there are two images in an "images" subdirectory. The two additional images may not have exactly the same pixel dimensions as the original, depending on your choice of full-width or not, the aspect ratio of the images perhaps, etc.
So this is rather intolerable, unless of course you can tell me what mistake I may have made. Otherwise, here's what I have done to get past this, and again, my question is would this work out in practice or do you have a better idea. I found this post on github, and in particular the comment by jerel concerning an insert_editor_js and wagtail_hooks.py hook. This overcomes the richtext limitations of standard hallo and permits opening a second editor window in which you can see and enter HTML.
But Wagtail has this Whitelister class that only permits certain attributes to be used with certain HTML tags. So the Wagtail people also have a hook for changing that, which is explained here. Here's my version of the wagtail_hooks.py file:
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.whitelist import attribute_rule, check_url, allow_without_attributes
from django.utils.html import format_html
# This one is from the esteemable jerel.
#hooks.register('insert_editor_js')
def enable_source():
return format_html(
"""
<script>
registerHalloPlugin('hallohtml');
</script>
"""
)
# This is modified from the Wagtail docs example.
#hooks.register('construct_whitelister_element_rules')
def whitelister_element_rules():
return {
'blockquote': allow_without_attributes,
'a': attribute_rule({'href': check_url, 'target': True}),
'img': attribute_rule({'src': True, 'width': True, 'height': True, 'alt': True, 'style': True}),
'p': attribute_rule({'style': True, 'class': True}),
}
Note especially that for the img tag I have put 'src': True in place of 'src': check_url, which is the default (check_url is a function that would reject a data URI, as I discuss below). Other changes important to me are the inclusion of 'target': True for the a tag and also the 'style': True additions.
Puput natively uses Bootstrap3 which is "mobile first", or some such rallying cry. So to bring about responsiveness for images with Bootstap3 in Puput I had to do what I have had to do before, which is, in the img tag, to either set the attribute width="100%" or to do it with style="width:100%;" (which I could do thanks only to the hallohtml plugin).
So now, here comes the problem: I found that that only works if you remove the extra attributes that Puput or Wagtail gives to the img tag (otherwise your changes will be deleted). Here's what the img tag looks like straight from the Puput editor: <img data-embedtype="image" data-id="9" data-format="fullwidth" data-alt="junk" class="richtext-image full-width" src="/home/mike/myproject/public_html/djangoprojectdir/public/media/images/imagename.width-800.png" alt="junk" height="1115" width="596">.
So if I throw away height and change width to 100% that doesn't work unless I also remove data-format, etc. If I do all of that, I have responsive design... but, the database is no longer involved. I have thereby instead just manually linked the image file to the img tag.
So my solution to bring about responsive-design behavior kills the database linkage between pages and image files. I must say, I don't miss the absurd presence of three images in the media folder for every one that I upload. And I don't much like having to guard and backup without failure, for years, not only a database but also a folder of many images.
So the second thing that I tried--- it too seems to work--- is the use of data URIs with Base64, which I read about here. It seems feasible because I won't be using many dense images. I made use of the hallohtml editor to cut and paste the Base64 encoding of the image to src in the img tag. It's not utterly unwieldy.
So again, the question is, do I have to do something like this (and is what I propose reasonable)... or, am I somehow just in the dark concerning how I should upload images or configure Puput and Wagtail for responsive design (I followed all of their instructions and everything else works)?
The root of the issue is that you need a good way of applying the style width: 100% to all rich text images. Ideally you'd do that with a global CSS rule, which would avoid the need to hand-edit the HTML of the body field.
Puput doesn't seem to provide an "official" way to customise the base templates at present, although there are a few pointers here: https://github.com/APSL/puput/issues/63. The following steps should hopefully do the trick:
Create a blog app inside your project (run ./manage.py startapp blog, and add 'blog' to the INSTALLED_APPS list in your settings making sure it's above puput) - or if your project already has a suitable app, follow the remaining steps with that app name in place of blog;
Create a blog/templates/puput/ directory
Create a file blog/templates/puput/base.html containing:
{% extends "puput/base.html" %}
{% block content %}
<style>
img.full-width {
width: 100%;
}
</style>
{{ block.super }}
{% endblock %}
I am looking for a simple way to organize stylesheets and scripts in Django. I am relatively new to the framework and language of python. I'm coming from a PHP background.
In the world of PHP / Zend there are functions that are implemented with the view/layout object. By including a single line inside your head tag for scripts and for stylsheets you can easily add a stylesheet/script in the view -> method level. I have read the Django Form Media Documentation, but this only pertains to forms needing specific styles and scripts.
Any direction?
Look at the django.contrib.admin application.
Parallel the way the admin site works.
Create a media directory.
Create media/img, media/jss, media/css, media/whatever directories
In each of these, you'll have your app's specific stuff. media/img/app1, media/jss/app1 so that each of your Django apps can have specific media without conflict or problems.
Be sure that your settings have the MEDIA_ROOT set. You'll want to read about this in the Django docs. You'll also have to set your MEDIA_URL for deployment. And you'll have to figure out how to make your webserver (i.e., Apache) serve this media.
Django should not be serving static files like .js libraries or .css files or any images. It's a waste of time. Apache can serve this just fine. For testing purposes, however, you can enable a simple file server capability in your Django site.
Finally. And most importantly.
Be sure that your page template actually references the various files you want to include on your page {{MEDIA_URL}}css/site.css, and {{MEDIA_URL}}js/app1/something.js.
Be aware that as of django 1.3, the old staticfiles app has become part of django.contrib.
The main thing to know is that you can stick your static media in a static/ subdir in any app that is in your settings.INSTALLED_APPS, and that file will be automatically collected by the collectstatic management command.
Rather than re-hash, I'll just point you at the docmentation: Django: the staticfiles app.
You might also want to consider looking for something that will process your text-based static files (css and javascript), which can easily be combined, minified and versioned. I'm about to look hard into this, so no links yet.
I like to have style-related images close to my stylesheets, and a different path for user uploaded content like profile pictures, photos, videos...
So I end-up with something like this:
/media
/style
base.css
img/
logo.gif
button.gif
/js
home.js
/profile
user_profile_image.gif
This way, image references inside css can be always relative like:
background: url(img/background.gif)
Also, there are some apps for handling media, css / js compression, sprites, etc.
It seems like you might actually looking for a way to conditionally include a stylesheet based on the current page. This can be done using template tags.
In your base.html file you would create a section to add stylesheets.
{% block addl_styles %}{% endblock %}
Then in the page you want to load the styles you would use the same block along with block.super to append your script to any other scripts called by your application.
So in your form's template you would use code like the following:
{% block addl_styles %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}your_css_folder/example.css" />
{% endblock %}
Please note that you can programmatically add the base dir using {{ MEDIA_URL }} and arrive at your folder in a safe manner.
I'm new to web development using python. I've good amount of experience in building dynamic websites using PHP. Also, I've never used MVC on PHP. For the first time I'm using MVC (or MTV to be more correct). I'm following
One thing different from PHP world is that. URLs doesn't point to files but to functions. This single point has made my experience in web development to zero. Its good for HTML content which can be generated from template.
But what about things that shouldn't be rendered like movies, images, pdfs, *.exes, stylesheets & javascript files. I mean for code like this:
<img src="image.jpg" />
or
<link rel="stylesheet" href="stylesheets/style.css" />
or
<a href="/downloads/huge_executable.exe" />
Do I need to write views for these too? If you say just one view like 'getNonRenderingContent' which reads the file and writes to http response with appropriate mime-type.
I feel its stupid & unnecessary load on the server. why should it run code for every such download. Is there any way to directly point urls to files instead of views?
You can configure your HTTP server to serve your files directly.
You can read about static files in Django here:
http://docs.djangoproject.com/en/dev/howto/static-files/