How You Should Start a Django Project
Django is a Python web framework with batteries included, but it doesn’t include all the batteries. This is a practical guide on how to structure and configure a Django project, with additional packages and my opinions. Some experience with Django is recommended. You can familiarize yourself with the basics using the official tutorial.
Inititialize the Project
Assuming you have uv installed, start a virtual package as our project (awesome_site):
1uv init --virtual awesome_site
Now delete the default main.py and create the Django skeleton project:
1cd awesome_site
2rm main.py
3uv add 'django==5.2.*'
4uv run django-admin startproject django_project
In the snippet above, I install Django 5.2 and start a django project called django_project.
The reason why I’m installing Django 5.2 is that Django x.2 are LTS versions and will get three years of support. Most the updates for Django LTS are security updates, so we don’t need to update our code very often. It could get annoying to need to update the code to match the latest Django.
I choose the name django_project for the Django project, though it can be anything. This is because, for one, the root project name awesome_site has been configured for uv. For another, Django configuration files will be stored in django_project/django_project, and this project name will help us find those files quickly when we need them.
Additional Packages
Several packages that you almost always need are environs, django-taggit, django-extensions and django-debug-toolbar.
environs
environs can be installed with this command:
1uv add 'environs[django]'
Not only can environs read environment variables and dotenv files, but it can also convert them to appropriate types for you. For example, list and dict environment variables are written like below:
1export GITHUB_REPOS=webargs,konch,ped
2# in Python:
3# print(env.list("GITHUB_REPOS"))
4# ["webargs", "knoch", "ped"]
5
6
7export GITHUB_REPO_PRIORITY="webargs=2,konch=3"
8# in Python:
9# print(env.dict("GITHUB_REPO_PRIORITY"))
10# {"webargs": "2", "konch: "3"}
With the django extension, environs can convert database connection strings to Django database settings. For instance,
1# Parse database URLs, e.g. "postgres://localhost:5432/mydb"
2DATABASES = {"default": env.dj_db_url("DATABASE_URL")}
is equivalent to writing the following:
1DATABASES = {
2 'default': {
3 'ENGINE': 'django.db.backends.postgresql',
4 'NAME': 'mydb',
5 'HOST': 'localhost',
6 'PORT': '5432',
7 }
8}
django-taggit
django-taggit makes the TaggableManager field available for your django models. This can be installed like below:
1uv add 'django-taggit'
It can be used like the following:
1print(apple.tags.all())
2# []
3
4apple.tags.add("red", "green", "fruit")
5
6print(apple.tags.all())
7# ["red", "green", "fruit"]
django-extensions
django-extensions is a collection of Django utilities. Use the following command to install it with uv:
1uv add django-extensions ipython
You also need to add it to your INSTALLED_APPS in django_project/django_project/settings.py:
1INSTALLED_APPS = (
2 # ...
3 "django_extensions",
4)
Frankly, I only use shell_plus to automatically load database models:
1uv run manage.py shell_plus
with this setting in django_project/django_project/settings.py to always use ipython:
1SHELL_PLUS = "ipython"
But do check out the documentation as you might find something interesting.
django-debug-toolbar
django-debug-toolbar is a sidebar that’s nice to have. Follow the official documentation to set this up.
Packages for RESTful API Development
To start, besides the Django REST Framework, you also need dj-rest-auth and django-allauth for more solid auth. Read their documents for better understanding.
WebSocket Configuration
You will need to firstly install channels. Channels is ASGI exclusive. That means you can only serve WebSocket endpoint via ASGI servers.
To configure channels, you create a protocol router to accept all traffic (HTTP and WebSocket) and route the HTTP traffic to your original Django application. Then you route WebSocket traffic to WebSocket consumer classes based on their request URL paths. Read channels tutorial for specific steps.
Background Tasks
You’ll need celery for this.
To install celery in the project above, you create a celery.py in django_project/django_project. In this file, initialize Django environment and the celery application, and then collect all the tasks from the project. After this, you can use celery alongside Django. For specific steps, follow the official documentation.