How to Manage Django Images and Static Assets on Ubuntu 18.04



Step 1: Initializing and Configuring the Project

1.1. Environment Initialization

$ sudo apt install python3             # Install Python3 interpreter
$ sudo apt install python3-pip # To manage python packages
$ sudo apt install python3-virtualenv # To manage virtual python environments
$ sudo apt install apache2 # To serve images and static assets
$ virtualenv --python=python3 venv     # This create the virtual environment venv
$ source venv/bin/activate # This is to activate the virtual environment
(venv)$ pip install Django==2.1            # Install Django v2.1
(venv)$ pip install Pillow # To manage images through Python code
(venv)$ pip install easy_thumbnails # To easyly manage image thumbnails

1.2. Project Configuration

(venv)$ django-admin startptoject photogallery
(venv)$ cd photogallery/
(venv)$ django-admin startapp gallery
(venv)$ pyhton migrate
(venv)$ python createsuperuser --username admin
(venv)$ Email address:
(venv)$ Password:
(venv)$ Password (again):
├── db.sqlite3
├── gallery
│ ├──
│ ├──
│ ├──
│ ├──
│ ├──
│ └──
└── socialgallery
(venv)$ python runserver
Starting development server at

Step 2: Configuring the Static Files Server

# Create static folders on the webserver
(venv)$ sudo mkdir /var/www/static
(venv)$ sudo mkdir /var/www/media
# Make static folders editable from the web browser
(venv)$ sudo chown -R www-data:www-data /var/www/static
(venv)$ sudo chown -R www-data:www-data /var/www/media
# Allow the group to write to the directory with appropriate permissions
(venv)$ sudo chmod -R 777 /var/www/static
(venv)$ sudo chmod -R 777 /var/www/media
# Add myself to the www-data group
(venv)$ sudo usermod -a -G www-data $(whoami)
STATIC_URL = '/static/'              # Used to include static resources in web pages
STATIC_ROOT = '/var/www/static/' # Used to get static resources from web server
MEDIA_URL = '/media/' # Used to include media items in web pages
MEDIA_ROOT = '/var/www/media/' # Used to get media items from web server
# This command will copy everything from the STATIC_URL to the STATIC_ROOT
(venv)$ python collectstatic

Step 3: Using Images and Static Files

{% load static %}
<img src={% static 'gallery/images/background.jpg' alt='Background Image' %}>
{% static 'gallery/css/bootstrap.css'%}
{% static 'gallery/js/bootstrap.js'%}
{% static 'gallery/js/jquery.js'%}

Step 4: Data Model Definition

from django.db import models
from django.contrib.auth.models import User
class Image(models.Model):
name = models.TextField(max_length='100')
path = models.ImageField()
number_views = models.IntegerField(default=0)
def __str__(self):
(venv)$ python make migrations    # This command will create migrations files
(venv)$ python migrate # Here the migrations created are executed

Step 5: Writing Views

from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import ListView, CreateView, DetailView, \
UpdateView, DeleteView
from .models import Image
class ImageListView(ListView):
model = Image
template_name = 'gallery/image_list.html'

class ImageDetailView(DetailView):
model = Image
template_name = 'gallery/image_detail.html'
class ImageCreateView(CreateView):
model = Image
template_name = 'gallery/image_create.html'
fields = '__all__'
class ImageUpdateView(UpdateView):
model = Image
template_name = 'gallery/image_update.html'
fields = '__all__'
class ImageDeleteView(DeleteView):
model = Image
template_name = 'gallery/image_delete.html'
success_url = reverse_lazy('image-list')

Step 6: Defining the URLs

from django.urls import path
from .views import ImageListView, ImageDetailView, ImageCreateView, \
ImageUpdateView, ImageDeleteView
urlpatterns = [
path('', ImageListView.as_view(), name='image-list'), # Will serve as homepage
path('<int:pk>', ImageDetailView.as_view(), name='image-detail'),
path('create', ImageCreateView.as_view(), name='image-create'),
path('update/<int:pk>', ImageUpdateView.as_view(), name='image-update'),
path('delete/<int:pk>', ImageDeleteView.as_view(), name='image-delete'),
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('images/', include('gallery.urls')),

Step 7: Creating HTML Templates

(venv)$ mkdir gallery/templates templates/gallery
{% block content %}
{% for image in object_list %}
<li>{{ }} - {{ image.path }} </li>
{% endfor %}
{% endblock %}
<p>name: {{ }}</p>
<p>Path: {{ object.path }}</p>
<p>Views: {{ object.number_views }}</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save Image">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update User">
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete the image "{{ }}"?</p>
<input type="submit" value="Confirm">

Step 8: Configure the Admin Dashboard

from django.contrib import admin
from .models import Image
class ImageAdmin(admin.ModelAdmin):
model = Image

Step 9: Testing Everything Works Well

(venv)$ python runserver


For Further Reading




Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store