Skip to content

Use Django’s system checks

Published on: December 20, 2023    Categories: Django, Python

This is part of a series of posts I’m doing as a sort of Python/Django Advent calendar, offering a small tip or piece of information each day from the first Sunday of Advent through Christmas Eve. See the first post for an introduction.

Check it out

While you can do very minimal Django setups, more typical use cases tend to involve a mix of applications — your own, some third-party, and some from django.contrib — and associated configuration, and while you can run a lot of “code quality” checks, it still can be daunting to verify you’re using and configuring Django correctly.

Which is where Django’s system-check framework comes in. The system check runs automatically as part of manage.py runserver and manage.py migrate, and can be explicitly run any time you like with manage.py check.

The system-check framework consists of a large number of built-in checks which look at your code and configuration and report problems (or things that are likely to be problems). You can also run subsets of checks corresponding to specific tags.

Notably, these are not static checks: they give you the ability to do live importing and introspection of code, and to run checks which see how things will actually look at runtime, which can be useful in a framework with as much runtime metaprogramming as Django.

For most Django apps you should consider running manage.py check regularly, and perhaps even as part of a CI process; manage.py check --deploy, or at the very least manage.py check --tag security, should probably run before you deploy anything, and should make sure to use the real deployment settings module (via the --settings flag to manage.py check) rather than local-dev or test-only settings.

You also can write your own system checks. The general idea is that you’re passed a list of applications to check (as Django AppConfig instances), and then you can do whatever you want with them: scan files in them, fetch a list of model classes, pretty much anything you like. If you’re writing an application which wants to be configured and used in a certain way, or even if you’re just doing some fancy things with custom models, managers, or model fields, writing some custom checks can be a good idea to make sure the code is being used as intended. For examples you can study the django/core/checks/ folder in Django itself. Model checks tend to make use of the undocumented/internal model-introspection API, though, so a future post may need to talk about how that works (it’s less scary than it sounds from that description).