Advanced Django Development: How to build a professional CMS for any business? (Part #3)
This article is based on the previous one. You can easily follow along by cloning The Official EngineerX Github repository and change directory to part-2:
git clone https://github.com/HsnVahedi/EngineerX
cd EngineerX/backend/part-2
Overview
In the previous article, we dockerized the application. Dockerizing an application makes us able to run it anywhere. We are guaranteed to always have exactly the same environment.
But what about data? Are we able to easily recreate our data?
Currently we don’t have any mechanism to programmatically insert objects into database.
Generating fake objects is the best solution. It can be useful in two places:
- generate data for tests: Normally you would like to initialize the database before running tests.
- Fill the database for demo: A web application with an empty database cannot be interesting. To represent our project to others, we fill the database with fake objects.
In part #3, we will see how we can generate images programmatically.
Generate image objects:
Follow these steps:
1) Download some images:
Download this folder and put it in WORKDIR/engineerx/
.
2) Configure the project to use images:
Set these variables in base.py
:
DOWNLOADS_ROOT = os.path.join(MEDIA_ROOT, 'downloads')
IMAGE_DOWNLOADS_DIR = os.path.join(DOWNLOADS_ROOT, 'images')
AVATAR_DOWNLOADS_DIR = os.path.join(DOWNLOADS_ROOT, 'avatars')
Your base.py
should now look like this file.
3) Update start.sh:
Add mv -vn downloads/ media/downloads/
to your start.sh
. That’s because our django application expects images to be located at /media/downloads/
.
Your start.sh
should now look like this file.
4) Add a module that generates image objects:
Create a new directory:
mkdir WORKDIR/engineerx/images
mkdir WORKDIR/engineerx/images/modules
Now add fakedata.py to WORKDIR/engineerx/images/modules/
:
import os
import loggingfrom django.conf import settings
from django.core.files import Filefrom wagtail.images import get_image_modellogger = logging.getLogger("fake users:")
Image = get_image_model()def create_dir_if_not_exists(directory):
if not os.path.exists(directory):
os.mkdir(directory)create_dir_if_not_exists(settings.MEDIA_ROOT)
create_dir_if_not_exists(settings.DOWNLOADS_ROOT)
create_dir_if_not_exists(settings.IMAGE_DOWNLOADS_DIR)
create_dir_if_not_exists(settings.AVATAR_DOWNLOADS_DIR)def create_wagtail_image(filename):
filepath = os.path.join(settings.IMAGE_DOWNLOADS_DIR, filename)
with open(filepath, "rb") as file:
image_file = File(file)
return Image.objects.create(file=image_file, title=filename)def create_wagtail_images():
images = []
files = os.listdir(settings.IMAGE_DOWNLOADS_DIR)
for file in files:
images.append(create_wagtail_image(file))
logger.info(
f'Successfully created image: {file}'
)
return images
By calling create_wagtail_images
, we can easily create image objects with files located at media/downloads/
.
5) Enable wagtail’s feature detection:
Wagtail has this awesome built-in feature to automatically detect the most important part of an image. Please checkout this if you are not familiar with wagtail.
To enable wagtail’s feature detection, set WAGTAILIMAGES_FEATURE_DETECTION_ENABLED = True
in base.py
.
Yourbase.py
should now look like this file.
6) Run in Development Environment:
Now it’s time to test our image generation mechanisms.
Build the docker image:
cd WORKDIR/engineerx/
docker build . -t engineerx/backend
Run development environment:
docker run -it -p 8000:8000 engineerx/backend bash
Create a media directory:
mkdir media
Move downloads
into media
:
mv -vn downloads/ media/downloads/
Run migrations:
python manage.py makemigrations && python manage.py migrate
Open a django shell:
python manage.py shell
Run this script to generate images:
>>> from images.modules import fakedata
>>> fakedata.create_wagtail_images()
Exit from shell:
>>> exit()
Create a superuser:
python manage.py createsuperuser
Run development server:
python manage.py runserver 0.0.0.0:8000
Now you can see the images are created by checking 127.0.0.1:8000/admin/images/
7) Run Production Environment:
Make sure to build the docker image:
cd WORKDIR/engineerx/
docker build . -t engineerx/backend
Start Production Environment:
cd WORKDIR/
export SECRET_KEY=<YOUR_SECRET_KEY>
export POSTGRES_PASSWORD=<YOUR_POSTGRES_PASSWORD>
docker-compose up
Now open another terminal and then open a django shell:
docker-compose exec backend python manage.py shell
Run this script in django shell:
>>> from images.modules import fakedata
>>> fakedata.create_wagtail_images()
>>> exit()
Create a superuser:
docker-compose exec backend python manage.py createsuperuser
Now you can see the images are created by checking 127.0.0.1:8000/admin/images/
Conclusion
In part #3, we have extended the existing project and added a module named fakedata.py
to easily generate images.
Just put the appropriate images in WORKDIR/engineerx/
and run a single function:
fakedata.create_wagtail_images()