Django from first principles
MP 90: Building a complete Django project from a single file.
Note: This is the first post in a series about building a full Django project, starting with a single file. This series will be free to everyone, as soon as each post comes out. 1
For a long time, Django has seemed more complex than other web frameworks such as Flask. This reputation is largely based on a somewhat unfair comparison between the "simplest" Django project and the "simplest" Flask project. That comparison often lands in favor of Flask, because Flask's documentation starts off with a single-file project consisting of just five lines of code.
In this project we'll build a Django project, but we'll take an approach that's much different from most Django tutorials. We'll start with a single file, just like the Flask example, and the single-file demos we see from other frameworks. As we build out the project, we'll add pieces one at a time, only as they're needed. By the time we're finished, we'll have a standard Django project built from the ground up.
The source of Django's (initial) complexity
Django's initial complexity stems from the fact that most tutorials tell people to start with these two commands:
$ django-admin startproject <project-name> . $ python manage.py startapp <app-name>
After running these two commands, there are twelve files you'll need to make sense of! If you're an experienced Django developer, that automatically-generated project structure is a big help. But if you're new to Django, it's not obvious at all how all these parts fit together.
An alternative approach
Rather than starting with these commands, we'll start with just one file that serves our project's home page. We'll look at all the parts of the file, so the purpose of every aspect of the project is clear from the start. As we progress in building out the project, we'll only expand out into additional files and directories when they're needed.
Where we'll end up
When the project is fully developed, we'll end up with a project structure that's almost identical to what you'd get using the startproject
and startapp
commands. You probably won't ever use the ground-up approach shown in this series again, but you'll come away from it with a much better understanding of the structure of a typical Django project.
A simple but nontrivial project
A good project for a tutorial series is simple, but nontrivial. This means it should use a database, incorporate user accounts, and feature styling that requires the use of static files.2
In this series we'll build a project called BlogMaker Lite. It's my go-to project for Django discussions, because it ticks all the requirements for a simple but nontrivial project. We'll also deploy the project when we're finished, to prove that the final version of the project would work in production.
Conclusions
Django is more complex than some other web frameworks, because it includes a lot more out of the box than minimalist frameworks. By the time you've built out everything your real-world project needs, a typical Django project isn't much more complex than a fully-built project using a different framework.
While startproject
and startapp
give experienced Django developers a nice starting point for new projects, people learning about Django don't need to start with the complexity that those two commands introduce. Instead, we can start from a single file that's easier to understand, and build out each new piece as it's needed.
If you're new to Django, hopefully this series will be a helpful way to see the framework for the first time. If you've been using Django for a while, you'll probably come away with a better understanding of the structure you've already been seeing in your projects. And if you're really experienced with Django, maybe you'll see the framework from a newcomer's eyes once again.
In the next post, we'll start by writing a single file that serves the project's home page.
Note: I'd love feedback throughout this series. If you have any thoughts or reactions, please leave a comment or reach out in whatever way works best for you.
Usually, new series on Mostly Python are only available to paid subscribers for a period of six weeks. This series will be free to everyone as soon as each post comes out. I'm still finishing up the migration from Substack, and it's a little easier to only publish free posts for a little while longer.
More importantly, I want this series to be available to people in the Django community as soon as each post is published. This series builds on work that people have been sharing at a number of recent DjangoCons, where people have been challenging each other to come up with the shortest working single-file Django project possible.
If you're curious about some of this prior work, start by watching Carlton Gibson's Djang0Con US 2019 talk, Using Django as a Micro-Framework. Then take a look at Will Vincent's django-microframework repository; Will has done a nice job of collecting a few different single-file examples. Then check out Paolo Melchiorre's μDjango project, which he demonstrated at DjangoCon US 2023. Andrew Mshar wrote an interesting blog post called Moving from Django Microframework to Django, following up on Paolo's work. Most recently, Andrew Godwin shared his django-singlefile project. This is the first example that seems to be meant for real-world use, and I'm curious to see where people go with it.
While these have been interesting exercises, it can quickly turn into a game of code golf. Someone might come up with slightly shorter single-file projects, but many of these are just as hard for newer people to understand as a standard Django project generated from startproject
and startapp
. I've been thinking for a while that one of the most interesting directions to take this work is building out a full project from one of these single-file examples. This series is my response to seeing everyone else's single-file projects; I hope the people who shared those projects like what they see here. :)
It frustrates me to no end seeing hosting platforms use overly simplistic Django projects in their examples. Heroku once pushed a broken build process because the sample project they used for testing didn't even use a database.