Django: An Unofficial Opinionated FAQ

By Kristian Glass

I really like Django. Django is fast, featureful, secure, scalable, and versatile. It works well with a variety of workflows, approaches, tools, platforms, and libraries.

But sometimes you can have too much choice.

I’ve spent a lot of time working with Django, and supporting other users via IRC in #django on Freenode. In that time I’ve seen a lot of the same questions come up again and again.

Django doesn’t provide official answers to many of these questions, and I don’t think it should - its versatility is one of its strengths. Here are my answers though - all of which are broad and given without knowing exactly what you’re doing - they’re not universally correct, but in the absence of knowing better, if you’re facing an unclear choice, then they should provide some clarity.

Good luck!

Should I use Flask or Django?

Django

If you’ve genuinely got a small self-contained thing, or code you just want to stick an HTTP API on top, then sure, I’d go with Flask.

Otherwise, I inevitably find the scope of my Flask services creeps, and so I end up bolting on more and more extra libraries and functionality, eventually finding myself wishing I’d started with Django instead.

What’s the best way to learn Django?

Whatever works best for you.

The official documentation is incredibly good and has spoiled me for other software I use, with its quality, breadth and depth.

My general recommendations are:

For further questions, I’ve learnt a lot from the community in #django on the Freenode IRC network.

Adam Johnson’s Where to Learn Django in 2019 takes a more in-depth look at these and more, including podcasts, videos, and meetups.

Should I split my code up into multiple apps?

Probably not.

Apps are great for if you’re shipping reusable functionality.

For your own stuff, especially when you’re just starting out, putting it all in one core app is usually best. At some point you’ll possibly hit a stage where you feel like you want to split things out more, at which point you’ll probably have some natural lines along which it will make sense to divide things. That’s often easier than trying to declare structure up front, and dealing with the consequences of changes.

Should I use Django’s default template language (DTL) or something else?

DTL.

It ships with Django by default, it works, it probably does everything you need.

DTL doesn’t do what I want - should I use something else like Jinja2?

Use DTL.

A common complaint is that DTL “isn’t expressive enough” - there’s assorted logic that you can’t do inside Templates.

I view this as a strength: it forces you to keep your logic inside Models and Views, while your Templates act as relatively simple display renderers - instead of having additional complexity living outside of your Python code.

Should I use Gunicorn or uWSGI to run Django?

Gunicorn.

Gunicorn does one thing - it’s a WSGI HTTP server - and it does it well. Deploy it quickly and easily, and let the rest of your stack do what the rest of your stack does well, wherever that may be.

uWSGI “aims at developing a full stack for building hosting services” - if that’s a thing you need then ok, but I like the principle of doing one thing well, and I deploy to platforms like Heroku and AWS Elastic Beanstalk where the rest of the “hosting service” is provided and managed for me.

Where should I deploy my app?

Heroku.

It’s the easiest Platform as a Service (PaaS) I’ve used.

If you need more levers or you’re tied to AWS, then AWS Elastic Beanstalk.

Platforms as a Service are your friend - yes you can get a cheap VM and install nginx and configure everything, but it’s an already-solved problem that they’ve solved cheaper (when you price your time) and generally better than you probably will.

Building your own Platform is like writing your own OS or web framework - not something to be undertaken lightly, especially when good ones already exist.

What should I use to serve my static files?

Whitenoise.

Amazon S3, Nginx, Apache etc. are all great, but Whitenoise is just a relatively small library that does a great job of serving static files without the moving parts of an extra service.

I’m trying to get the admin to do X…

Maybe stop.

Django’s admin is an excellent piece of software. But to quote Django’s own documentation:

The admin’s recommended use is limited to an organization’s internal management tool. It’s not intended for building your entire front end around.

The admin has many hooks for customization, but beware of trying to use those hooks exclusively. If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.

If you’re banging your head against a wall trying to figure out how to bend the admin to your will, then there’s a good chance you should stop, and go build something with Django’s powerful generic views.

What database should I use?

PostgreSQL.

It just works.

Other databases like MySQL and MariaDB definitely also just work (though you probably don’t want SQLite outside of development or relatively niche production setups) but PostgreSQL is the one I’ve found easiest to work with, and it has a bunch of support within Django.

How should I split my settings file between production / development?

Don’t.

The Twelve-Factor App covers a range of reasons why in-app per-environment settings files and the like can be problematic, and why it’s worth using environment variables instead.

django12factor and other apps exist to help you get configuration from the environment.

Should I use a custom User model?

From the official documentation:

If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you. This model behaves identically to the default user model, but you’ll be able to customize it in the future if the need arises.

If you’re mid-development, things are a little trickier…

This change can’t be done automatically and requires manually fixing your schema, moving your data from the old user table, and possibly manually reapplying some migrations.

My question isn’t answered here!

Leave a comment, catch me on Freenode, or send me a tweet and I’ll see what I can do!