Chapter 21 · Management commands

21.7 The commands Django ships

The management commands that come with Django, by what each one drives: those of django/core/management/commands/ and those of the contrib applications, the few whose classes reach into the machinery instead of only filling in handle, and the base class behind startproject and startapp, TemplateCommand.

Most of Django’s commands are thin fronts. Such a command’s handle reads the options, picks a database connection or a few applications, and hands the work to a subsystem that would do the same if it were called from anywhere else. To know what migrate really does is to know the migration executor, and the command’s module is the wrong place to look for that. A few carry their work themselves: inspectdb writes model source from what a database reports, makemessages drives a set of external programs, the shell builds a namespace. So this page is mostly a map from each command to the code that does its work, and from there to the chapter that explains it.

Django’s own commands

These are the modules of django/core/management/commands/, which are commands in every project and the only commands where there are no settings.

Table 21.4 The commands of django/core/management/commands/, by what does their work.
command its handle hands the work to told in
makemigrations its handle hands the work to the autodetector, which compares the models with the state the migration files describe, and the writer, which turns the difference into files MigrationAutodetector.changes django/db/migrations/autodetector.py told in The makemigrations command
migrate its handle hands the work to the executor, which applies or unapplies migrations to reach a target; the command sends the pre_migrate and post_migrate signals around it MigrationExecutor.migrate django/db/migrations/executor.py told in The migrate command, showmigrations and sqlmigrate
showmigrations its handle hands the work to the loader’s graph and the recorder’s table, to list migrations or the plan Command.show_list django/core/management/commands/showmigrations.py told in The migrate command, showmigrations and sqlmigrate
sqlmigrate its handle hands the work to the loader, which runs one migration against a schema editor that collects SQL and executes nothing MigrationLoader.collect_sql django/db/migrations/loader.py told in The migrate command, showmigrations and sqlmigrate
squashmigrations, optimizemigration its handle hands the work to the optimizer, which shortens a list of operations, and the writer MigrationOptimizer.optimize django/db/migrations/optimizer.py told in Squashed migrations: replaces and the squashmigrations command, The optimizer: MigrationOptimizer and reduce
dbshell its handle hands the work to the backend’s client class, which runs the database’s own command-line program BaseDatabaseClient.runshell django/db/backends/base/client.py told in The connection object: BaseDatabaseWrapper and what a backend provides
inspectdb its handle hands the work to the backend’s introspection, from whose answers the command prints model source BaseDatabaseIntrospection django/db/backends/base/introspection.py told in Introspection: reading the schema back
sqlflush its handle hands the work to a function that picks every existing table of the installed, managed models and has the backend’s operations build the statements that would empty them sql_flush django/core/management/sql.py told in Introspection: reading the schema back
flush its handle hands the work to the same statements, executed, and then the post_migrate signal BaseDatabaseOperations.execute_sql_flush django/db/backends/base/operations.py told in Introspection: reading the schema back
sqlsequencereset its handle hands the work to the backend’s operations, for the statements that reset the sequences of some applications’ tables BaseDatabaseOperations.sequence_reset_sql django/db/backends/base/operations.py told in Introspection: reading the schema back
dumpdata its handle hands the work to a serializer, fed the rows of the chosen models serialize django/core/serializers/__init__.py told in Fixtures: dumpdata and loaddata
loaddata its handle hands the work to a deserializer, inside one transaction with constraint checking put off to its end Command.loaddata django/core/management/commands/loaddata.py told in Fixtures: dumpdata and loaddata
createcachetable its handle hands the work to nothing else: the command builds the statements for the database cache’s table itself Command.create_table django/core/management/commands/createcachetable.py told in The cache backends
sendtestemail its handle hands the work to the mail functions send_mail django/core/mail/__init__.py told in Sending email: mailers and the email backends
makemessages, compilemessages its handle hands the work to the GNU gettext programs, run as child processes popen_wrapper django/core/management/utils.py told in Making catalogues: makemessages and compilemessages
test its handle hands the work to the test runner class, named by --testrunner or else by settings.TEST_RUNNER, and its method that runs the tests DiscoverRunner.run_tests django/test/runner.py told in The runner: the test command and DiscoverRunner
listurls its handle hands the work to a walk over the root URLconf’s patterns extract_views_from_urlpatterns django/urls/utils.py told in URL routing
diffsettings its handle hands the work to a comparison of the loaded settings with global_settings.py django/conf/ Command.handle django/core/management/commands/diffsettings.py told in Settings, apps and startup
check its handle hands the work to the check framework BaseCommand.check django/core/management/base.py told in The system checks
runserver its handle hands the work to the development server run django/core/servers/basehttp.py told in The development server
testserver its handle hands the work to the code that makes a test database, and then the loaddata and runserver commands, called from code Command.handle django/core/management/commands/testserver.py told in The development server
startproject, startapp its handle hands the work to TemplateCommand told in below
shell its handle hands the work to an interactive interpreter told in below

Some functions that several of these share live beside the commands. emit_pre_migrate_signal and emit_post_migrate_signal send the two signals once for each installed application that has a models module; migrate calls both, and flush the second. And run_formatters runs the Black formatter, if one is installed, over the files or the directory a command has just written; the migration commands that write files and the two template commands call it.

The commands of the contrib applications

A contrib application’s commands exist in a project that installs the application, and are found like any other application’s (Finding the command).

Table 21.5 The commands of the contrib applications. createsuperuser and changepassword are told in Creating a superuser: createsuperuser and changepassword, clearsessions in The session backends, and the others belong to Content types, static files and the other contrib apps.
application command what it does
django.contrib.auth command createsuperuser what it does asks for, or reads from the environment, the fields of the user model, and calls the model manager’s method that makes a superuser Command.handle django/contrib/auth/management/commands/createsuperuser.py
command changepassword what it does asks for a password twice, validates it and saves it on the user Command.handle django/contrib/auth/management/commands/changepassword.py
django.contrib.contenttypes command remove_stale_contenttypes what it does deletes the content types of installed applications whose model no longer exists, after listing, when it can ask for confirmation, what would go with them Command.handle django/contrib/contenttypes/management/commands/remove_stale_contenttypes.py
django.contrib.sessions command clearsessions what it does calls the session engine’s method that removes expired sessions SessionBase.clear_expired django/contrib/sessions/backends/base.py
django.contrib.staticfiles command collectstatic what it does copies or links into the static files storage the first file found for each path among those the finders list, then lets the storage process them Command.collect django/contrib/staticfiles/management/commands/collectstatic.py
command findstatic what it does asks the finders where a file is find django/contrib/staticfiles/finders.py
command runserver what it does Django’s runserver, with static files served (The development server)
django.contrib.gis command inspectdb what it does Django’s inspectdb, taught the geometry column types Command django/contrib/gis/management/commands/inspectdb.py
command ogrinspect what it does prints model source for a layer of a geographic data file _ogrinspect django/contrib/gis/utils/ogrinspect.py

Two of them have the name of a command of Django’s and take its place, each by subclassing the class it displaces.

The name management has a second use. The auth, contenttypes and sites applications each keep, in a module of that name, the functions that run when migrate has finished its work, to create permissions, content types and the default site among other things, and connect them to post_migrate in their AppConfig.ready. For an application that connects such receivers in the module itself, migrate and flush import the management module of every installed application at the start of their handle.

The few that reach into the machinery

A command usually leaves BaseCommand alone and defines add_arguments and handle. This is what each class of the recorded project’s Django does beyond that: which of the attributes that steer the machinery its own class sets, and which methods of the machinery it overrides. The class’s help text and its message for missing arguments, which many set, are not counted. Classes of django.core that do neither are left out, with a line of dots where they were.

The commands of django.core and of django.contrib.staticfiles: the base of each, and what its own class sets and overrides of what BaseCommand defines
    django.core
      check  (BaseCommand)
        requires_system_checks = []
      compilemessages  (BaseCommand)
        requires_system_checks = []
      createcachetable  (BaseCommand)
        requires_system_checks = []
      dbshell  (BaseCommand)
        requires_system_checks = []
      diffsettings  (BaseCommand)
        requires_system_checks = []
      ...
      flush  (BaseCommand)
        stealth_options = ["reset_sequences", "allow_cascade", "inhibit_post_migrate"]
      inspectdb  (BaseCommand)
        requires_system_checks = []
        stealth_options = ["table_name_filter"]
      listurls  (BaseCommand)
        overrides __init__
      ...
      makemessages  (BaseCommand)
        requires_system_checks = []
        requires_settings = False
      ...
      migrate  (BaseCommand)
        overrides get_check_kwargs
      ...
      runserver  (BaseCommand)
        stealth_options = ["shutdown_message"]
        suppressed_base_arguments = ["--traceback", "--verbosity"]
        overrides execute, get_check_kwargs
      ...
      shell  (BaseCommand)
        requires_system_checks = []
        requires_settings = False
      ...
      sqlflush  (BaseCommand)
        output_transaction = True
      sqlmigrate  (BaseCommand)
        output_transaction = True
        overrides execute
      sqlsequencereset  (AppCommand)
        output_transaction = True
      ...
      startapp  (templates.TemplateCommand)
        requires_settings = False
      startproject  (templates.TemplateCommand)
        requires_settings = False
      test  (BaseCommand)
        requires_system_checks = []
        overrides run_from_argv
      testserver  (BaseCommand)
        requires_system_checks = []
    django.contrib.staticfiles
      collectstatic  (BaseCommand)
        requires_system_checks = ["staticfiles"]
        overrides __init__
      findstatic  (LabelCommand)
      runserver  (runserver.Command)

About half ask for no system checks, counting the two template commands, which inherit an empty list from TemplateCommand. Two of those run the checks themselves, at a time of their choosing: check, whose whole purpose it is, and test, whose runner calls check once the test databases exist; a comment in the test command says so. The rest are the two that make a project or an application, shell and dbshell, the two for translation files, and inspectdb, diffsettings, createcachetable and testserver.

Four can run without settings, the two that create a project or an application, the shell, and makemessages (Finding the command).

A handful override a method of the machinery, and each for a reason of its own.

One more is not in the recording because its application is not installed there. The createsuperuser command overrides __init__, to find the user model before its arguments are declared, and execute, to accept in place of standard input a stream that it asks only whether it is a terminal, declared as a stealth option and, its comment says, used for testing; its prompts still read standard input (Creating a superuser: createsuperuser and changepassword).

Commands that write a project: TemplateCommand

startproject and startapp are one class with two names. Each is a TemplateCommand whose handle passes on the word “project” or “app”, and the project one adds a freshly generated secret key.

TemplateCommand.handle copies a directory, and renders some of the files on the way.

  1. It checks the name: a valid Python identifier, and not the name of a module that can already be imported, with which the new one would conflict.
  2. It makes or accepts the target directory.
  3. It prepares the template engine. With no settings configured it configures the defaults and calls django.setup, so that the engine can run in an empty directory (Who calls django.setup).
  4. It finds the template directory. By default that is django/conf/project_template/ or django/conf/app_template/. With --template it is a directory, or an archive that is unpacked into a temporary place, or a URL that is downloaded first.
  5. It walks the template directory, creating each directory and file under the target, with the placeholder in a file’s or a directory’s name replaced by the real name. Compiled Python files are passed over, and so are hidden directories, or with --exclude the directories that option names. A file whose extension is one of those to render, .py and any that --extension adds, or whose name --name lists, is passed through the Django template language with the name, the directory, Django’s version and a few more values as its context; every other file is copied as it is. A file that already exists at the destination stops the command.
  6. It runs a formatter over the target directory, if one is installed. It looked for the formatter before step 4, so that nothing a template brought with it could be found in its place.

Two details of step 5 explain the look of the template directories. Their Python files are named with -tpl after the extension, and the command removes it when it writes them: a comment gives the reason, that a file full of template tags is not valid Python and must not be compiled when Django is installed. And the rendering is done with autoescaping off.

The shell

The shell command starts an interactive interpreter in a process where Django has been started. It tries IPython, then bpython, then Python’s own code module, and uses the first that can be imported, or the one --interface names. With --command it executes a string and exits, and where the platform allows it does the same with whatever is piped to its standard input.

What it adds to a bare interpreter is a namespace. Command.get_auto_imports in that file returns a list of dotted paths, and each is imported and bound under its last part: the settings object, the default database connection, the ORM’s modules of models and of database functions, the function that empties the log of queries, the timezone module, and then every model class the app registry lists, which leaves out the models made automatically for many-to-many relations and the models that have been swapped for others. Where two models have the same name, the one from the application listed earlier in settings.INSTALLED_APPS is the one bound. A project changes the list by subclassing the command and overriding that method, in an application of its own.

The command declares that it can run without settings. When there are none, it says that automatic imports are off, and why, and starts the interpreter with an empty namespace.