12. Images

Robert Crowther Mar 2022
Last Modified: Feb 2023

PrevNext

Now you have working pages, at least from models, you will probably want images. Some document websites work without them but most will need a few, perhaps many.

Aside, I give you no answers here, only talk.

Static images

This is all I need for development. For some sites, it is all that is needed. Images deployed statically are dropped into the static directories by the developers. Images deployed like this can be used for logos, icons etc. To some extent, staticly deployed images can also be used in page development, by placing temporary links into template code. This works good for a while, but it’s not a solution for user upload of files to a site.

The role of ‘static’

Remember what ‘static’ does. It searches for ‘static’ named app, and other predefined, directories, then gives you a URL that can be used to deliver these files. All sources on one URL. Come the time to deploy, there is a command to gather these resources together, so they can go to one place on a server, perhaps even a different server to the site.

This is the same for images deployed as static as for JS/CSS files. See Django doumentation on static files.

Shortcut images using ‘static’

Raw placement of images into Django. I find this is enough to support most site development. It lets me source utility images, such as icons, and placeholder images, such as test images for articles etc.

In siteName/static make a new directory,

mkdir siteName/static/images

Place an image inside. This should now be available on the static URL e.g.

http://127.0.0.1:8000/static/images/park.jpg

You can use the image in templates,

{% load static %}
    ...
    <img src="{% static 'images/park.jpg' %}">

Uploads

Image uploading is rather more complex than a few static images.

Strategy

For image uploading, you need a strategy.

Some websites store files in online repositories, such as AWS. I’m not going into the advantages and disadvantages. Django has a generalised concept of a ‘file’. A ‘file’ can have a ‘source’ that is up‐and‐down loadable through URLs. You can find apps that, with some configuration, will use Django ‘files’ to handle online repositories for you. Bear in mind, when using an online repository, ‘download’ means generating URLs that point to the online repository. To start, see the Django documentation on files and file storage. Then look at some apps.

Despite these modern solutions, and the advantages they have, many websites still use local upload solutions. Advocates of online storage will tell you their solution is faster, more robust and secure. But ‘local’ storage, on your own server, is cheaper and less administration. So don’t be put off.

Local uploading

Support libraries, Pillow

Most image uploading needs some support libraries. These libraries do things like discover information, or edit, through code. Different code needs different libraries. However, the base code of Django uses a Python library called Pillow, so you may as well get that installed,

pip install Pillow

The role of ‘media’

Unfortunately, the word ‘media’ is used twice in Django. It is used for transfering attributes through sub‐classes, and for uploaded file targets. If you are doing a search, concentrate on results for files and uploading.

Django has a concept for dealing with file uploads, This is not built into a skeleton, but is present in core code. Uploaded files go to a directory usually called ‘media’. Uploaded files are served through a URL, usually,

/media/fileName.jpg

Or similar.

Goto siteName/settings.py, and add this, under the STATIC settings. Names can be anything, I prefer to be explicit,

# Base url to serve media files
MEDIA_ROOT = BASE_DIR / 'files_upload'

# Path where media is stored
MEDIA_URL = 'media/'

Now you need to make the directory,

mkdir files_upload

Work is not finished. Apps will use those settings for media uploading, but there is no serving. To serve in a development environment, add this code to urls.py,

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

While it is quite possible to change and append these settings, other code will be deriving upload targets and URLs from them. So I wouldn’t change them except by way of siteName/settings.py, even though you added these lines by hand. They are a convention.

Right, that’s the basics of local storage placement and URL delivery.

Git

If you are using Git, you probably don’t want to commit gathered static files. So add the MEDIA_ROOT to the .gitignore,

files_upload/**

Uploading files

Now, you yell at me, “But how do I upload?” I suggest you start thinking how you want to handle uploaded files, then go look at some apps. I’ll tell you why…

Every tutorial I have seen builds a simple upload form. Personally, I find that a useless contribution. File uploading needs a strategy. Are you going to upload images/documents associated with other models e.g. ‘Main product photo’? In which case, you probably want image upload widgets on the model form. Or do you want an image pool, for general images? In which case your image upload form is likely more complex. Would it be a good idea to categorise the images (hint: yes. If you have more than twenty then finding files on a general form will become tedious/impossible)? Or do you want special and general uploads, both, so need two paths of file uploading?

And that’s only the start of your considerations. As mentioned above, you need to think where these uploads are being stored. Then consider how to categorise storage. Or would you prefer a general pool of storage? The stock Django upload system tracks uploads in the database, so it knows where files ‘are’. Then again, maintenance will be easier if storage positions are categorised. And, important, what is your delete policy? If a file is used in several places, then is deleted, that action will cause caos—a variation of the old dependency problem. On the other hand, storing files is expensive. If EBay keeps every file they are given, there would be no storage left in the world. Note: Django has a policy about this, and the policy has changed. Nowadays, when database information is changed, Django will not delete files.

And that’s before I talk about deployment and servers, which has a huge effect on file handling. When I say huge, your site build may well be built around your deployment strategy. You need to look at all this, make a way through it, before you have a deployable website.

Refs

Build a simple form for uploads.

https://www.ordinarycoders.com/blog/article/django-file-image-uploads