In this article, I'll discuss the Django management commands you should know as a beginner or advanced developer. So, without further ado, let's get started to explore the core commands available in Django and other libraries and how to write your custom management commands.

Before going further, let us understand the importance of the management command. A command is a simple Python module extended by a Django base command, and this module is mainly used as Django's command-line utility for administrative tasks. To run any Django management commands, we use the manage.py module; this module is auto-generated at the root folder level when we install the Django project.

As an alternative to manage.py, we can use django-admin to execute the management commons. So in our below discussions, we will prefer the manage.py command-line utility.

Table of contents 📝

  • Explanation of the Django core commands.
  • Other library extension Django commands.
  • Custom Django commands.

1. Explanation of the Django core commands.

When we are working on any projects, we list all the available management commands using python manage.py, so I created simple Django project in which I can see most of the Django core management commands.

python manage.py
Type'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:

[auth]
 changepassword
 createsuperuser

[contenttypes]
 remove_stale_contenttypes

[django]
 check
 compilemessages
 createcachetable
 dbshell
 diffsettings
 dumpdata
 flush
 inspectdb
 loaddata
 makemessages
 makemigrations
 migrate
 optimizemigration
 sendtestemail
 shell
 showmigrations
 sqlflush
 sqlmigrate
 sqlsequencereset
 squashmigrations
 startapp
 startproject
 test
 testserver

[sessions]
 clearsessions

[staticfiles]
 collectstatic
 findstatic
 runserver
these core commands are available in 
my_virtual/lib/{your python version}/site-packages/django/core/management/commands 
location

➡️ runserver

python manage.py runserver 

The runserver command is used to run the Django server, but by default, when we run this command, Django will run at port 8000.

Watching for file changes with StatReloader
Performing system checks…
System check identified no issues (0 silenced).
September 04, 2024–01:40:06
Django version 4.2.16, using settings 'hemanth.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

we can also change the port to any port number, here I changed it to 3000

python manage.py runserver 3000

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
September 04, 2024 - 01:41:33
Django version 4.2.16, using settings 'hemanth.settings'
Starting development server at http://127.0.0.1:3000/
Quit the server with CONTROL-C.

for runserver, you can pass some extra options like

[--nothreading] [ --noreload] [--nostatic] [ --insecure] [--version] [--settings SETTINGS]
 [ — pythonpath PYTHONPATH] [ — no-color] [ — force-color] [ — skip-checks]
 [addrport]

For example, when we make any code changes, the Django server does an auto-reload using the runserver command, but we can disable this auto-reload using the no-auto-reload option with the runserver

$ python manage.py runserver --noreload

➡️ collectstatic

To use this command, make sure you have the django.contrib.staticfiles app inside the application definition that is INSTALLED_APPS.

python manage.py collectstatic

When we run this command, Django will collect all the static files in our project and put them in the destination folder. That destination folder we need to define in the settings.py file using STATIC_ROOT.

for example

STATIC_ROOT = os.path.join(BASE_DIR, 'whole-static')
python manage.py collectstatic
125 static files copied to '/home/{my laptop folders}/hemanth/whole-static'.

➡️ createsuperuser

used to create a Django superuser so that this user can log in to http://127.0.0.1:8000/admin.

$ python manage.py createsuperuser
Username (leave blank to use 'hemanth'): hemanth
Email address: [email protected]
Password: 
Password (again): 
Superuser created successfully.

➡️ changepassword

used to change the given username and password

$ python manage.py changepassword hemanth
Changing password for user 'hemanth'
Password: 
Password (again): 
Password changed successfully for user 'hemanth'

inside the changepassword module, this was the code

u = User.objects.get(username="hemanth")
u.set_password("enterd_password")
u.save()

➡️ check

used to check the entire Django project for potential problems. For example, when we define the wrong field option in the model's field like (fields.W340) null does not affect ManyToManyField.

python manage.py check

or when we want to deploy our project at that time, we can use this

python manage.py check --deploy

➡️ dbshell

This will activate the PSQL command line for the given database. in this example, I am using PostgreSQL DB

$ python manage.py dbshell
Signals Started
psql (14.13 (Ubuntu 14.13–0ubuntu0.22.04.1), server 12.18 (Ubuntu 12.18–0ubuntu0.20.04.1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
vip=# \l
                                List of databases
       Name       |  Owner   | Encoding | Collate | Ctype |   Access privileges   
------------------+----------+----------+---------+-------+-----------------------
 asd              | postgres | UTF8     | en_IN   | en_IN | 
 car              | postgres | UTF8     | en_IN   | en_IN | 

➡️ diffsettings

Displays differences between the current settings.py and Django's default settings. However, we never used this.

$ python manage.py diffsettings

➡️ Flush

This will remove all the data from the database except migrations; however, never use this production

$ python manage.py flush
You have requested a flush of the database.
This will IRREVERSIBLY DESTROY all data currently in the "/home/project/hemanth/db.sqlite3" database,
and return each table to an empty state.
Are you sure you want to do this?
yes
Type 'yes' to continue, or 'no' to cancel: yes

➡️ inspectdb

This will display all the database tables from your default database to the Django model format, and this will help write the Django model from the existing database table.

$ python manage.py inspectdb
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models

class AuthGroup(models.Model):
 name = models.CharField(unique=True, max_length=150)

class Meta:
 managed = False
 db_table = 'auth_group'

➡️makemigrations

This is one of the main utility commands after runserver; this one is used to generate migration files for your modified Django models, or if you installed any third-party libraries, so we also need to generate migration files. This migration file contains SQL commands and queries.

python manage.py makemigrations
# No changes detected
or
files will be generated.
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Student

➡️ migrate

After the migration files are generated, we need to apply those (our model changes) to the physical database, so at that time we need to use this command.

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying polls.0001_initial... OK

➡️ shell

shell is the interactive console where we can execute Django (only installed project packages and modules) or Python code for debugging purposes.

$ python manage.py shell

Python 3.9.19 (main, Apr  6 2024, 17:57:55) 
[GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 
>>> from django.contrib.auth.models import *
>>> User.objects.count()
0

➡️ showmigrations

This will display all the executed and not executed migration files (0002_student_age).

$ python manage.py showmigrations
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
polls
 [X] 0001_initial
 [ ] 0002_student_age
sessions
 [X] 0001_initial

➡️ startapp

This command will be used to create the Django apps, and after creating the app, make sure to include the installed app. For example, I created polls apps and included them in the installed app section.

python manage.py startapp polls
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls'
]

➡️ startproject

This is the first command used to create the Django project.

python manage.py startproject my_project_name

➡️ test

This command will be used to run all the Django test cases that we usually write inside all the apps.

python manage.py test
Found 0 test(s).
System check identified no issues (0 silenced).
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — 
Ran 0 tests in 0.000s
OK

➡️ testserver

This command is a combination of loaddata and runserver commands. We can use this to run a server with some initial data, and this data will be loaded into a new test db.

$ python manage.py testserver



Creating test database for alias 'default'…
CommandError: Error: No database fixture specified. Please provide the path of at least one fixture in the command line.

➡️ clearsessions

This will clear all the session data stored in the defined module; this is the default module to store the session data.

$ python manage.py clearsessions
# The module to store session data
SESSION_ENGINE = "django.contrib.sessions.backends.db"

➡️dumpdata

If we need a dump of data either from a database or a particular table or model in JSON format, then we can use the command; this will display the model's data in the given format by default as JSON.

For example, I need only a dump of all models inside the Polls app; in that case, I use this command in this format by passing the Polls app.

python manage.py dumpdata polls
[
  {
    "model": "polls.student",
    "pk": 1,
    "fields": {
      "name": "hemanth",
      "age": "90"
    }
  },
  {
    "model": "polls.student",
    "pk": 2,
    "fields": {
      "name": "joy",
      "age": "89"
    }
  }
]

If we need a JSON file instead of displaying the dump, then

$ python manage.py dumpdata polls > polls_dump.json

this command will create the dump file in the root folder.

➡️ loaddata

to load the dumped data into our models, then we can use this command

$ python manage.py loaddata polls_dump.json
Installed 2 object(s) from 1 fixture(s)

Note: While using load data, keep an eye on the primary key because if the same objects are already there in the database, those from the fixture with the same primary key will be updated, or else an object will be created.

2. Other library extension Django commands.

None
Other library extensions

There are many third-party packages; however, Django extensions are the most important and most used ones.

Before displaying what are all the management commands in this package, let us install the package first.

install the package.

$ pip install django-extensions

Add this app to the installed apps section.

INSTALLED_APPS = [
    ...
    'django_extensions',
    ...
]

now display all the commands

$ python manage.py
[django_extensions]
 admin_generator
 clean_pyc
 clear_cache
 compile_pyc
 create_command
 create_jobs
 create_template_tags
 delete_squashed_migrations
 describe_form
 drop_test_database
 dumpscript
 export_emails
 find_template
 generate_password
 generate_secret_key
 graph_models
 list_model_info
 list_signals
 mail_debug
 managestate
 merge_model_instances
 notes
 pipchecker
 print_settings
 print_user_for_session
 raise_test_exception
 reset_db
 reset_schema
 runjob
 runjobs
 runprofileserver
 runscript
 runserver_plus
 set_default_site
 set_fake_emails
 set_fake_passwords
 shell_plus
 show_template_tags
 show_urls
 sqlcreate
 sqldiff
 sqldsn
 sync_s3
 syncdata
 unreferenced_files
 update_permissions
 validate_templates

So in total, this Django extension package gives 47 utility commands. we will explore only what we use every day

➡️ clean_pyc

This will delete all the.pyc (python bytecode compiled files from the project.") from the projects that were by default created by Python and available inside this __pycache__ folder.

$ python manage.py clean_pyc

➡️ create_command

This will be used to create a scaffold to create custom management commands, and I will explain how to write custom management commands in a later section of the article.

So, for example, I want to create a Django management command directory structure in the polls app. The create_command will create a folder structure in the Polls app with the sample.py module as an example.

$ python manage.py create_command polls

➡️describe_form

the command used to auto-generate and display the Django form format of the given model

$ python manage.py describe_form polls.student
from django import forms
from polls.models import Studentclass StudentForm(forms.Form):
 name = forms.CharField(label='Name', max_length=100)
 age = forms.CharField(initial=1, label='Age', max_length=100)

➡️ generate_password

This will be used to generate the random password based on the Django core's default password generator, BaseUserManager.make_random_password() method.

$ python manage.py generate_password --length=100

The output will be like this; the length parameter is a must.

3T35szkZ6xc79Gg8Q3AuqJz6VRwCptsmkePss7rcxR7V4KGdFAZNtFXerg88RQ4tbDNPqqsM5VtH5A4HwZXsNfVMYgzwS5ERRHrQ

➡️ graph_models

used to generate the graph relation of models in different output formats; for example, let me create a graph model for the entire project.

$ python manage.py graph_models polls -a -o myapp_models.png
CommandError: Neither pygraphviz nor pydotplus could be found to generate the image. To generate text output, use the — json or — dot options.

so I installed pydotplus

$ pip install pydotplus

in the root folder, the image was created

None

or we can generate for one app, like this

$ python manage.py graph_models polls -o myapp_models.png
None

➡️ list_model_info

command, which lists given model fields and methods.

$ python manage.py list_model_info --model=polls.student

polls.Student
 Fields:
    id -
    name -
    age -
 Methods (non-private/internal):
    adelete()
    arefresh_from_db()
    asave()
    get_constraints()
    validate_constraints()
Total Models Listed: 1

➡️ notes

will print all annotations like TODO, FIXME, BUG, HACK, WARNING, NOTE, or XXX in your py and HTML files

for example

from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=100)
    # TODO make
    age = models.CharField(max_length=100, default=1)
$ python manage.py notes
/home/hemanth/polls/models.py:
 * [ 7] TODO make

➡️ pipchecker

will display all the outdated pip packages by scanning our requirements.txt file.

$ python manage.py pipchecker

for example

amqp 5.1.1 5.2.0                available
annotated-types 0.6.0 0.7.0     available
anyio 4.3.0 4.4.0               available
.....................
.....................

➡️ raise_test_exception

If you want to raise an exception instead of manually raising it while installing a third-party library like Sentry, for example, after integrating Sentry, we need to test Sentry to see if it is catching our exception or not to do data. The documentation mentioned creating an API with logic 1/0 so that an error will occur, but instead of doing all this, we can simply run these commands.

$ python manage.py raise_test_exception
django_extensions.management.commands.raise_test_exception.DjangoExtensionsTestException: This is a test exception via the
django-extensions raise_test_exception management command.

➡️ reset_db

this deletes all the data from your database, so keep an eye on the production

$ python manage.py reset_db
You have requested a database reset.
This will IRREVERSIBLY DESTROY
ALL data in the database "/home/hemanth/Downloads/hemanth/db.sqlite3".
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel: yes
Reset successful.

➡️ shell_plus

This is exactly like Django Shell, but it has a lot of features, like autoloading all models, and we can pass some extra parameters that will be helpful to debug SQL queries.

for example, here our student model is also pre-loaded

$ python manage.py shell_plus
# Shell Plus Model Imports
from django.contrib.admin.models import LogEntry
from django.contrib.auth.models import Group, Permission, User
from django.contrib.contenttypes.models import ContentType
from django.contrib.sessions.models import Session
from polls.models import Student
# Shell Plus Django Imports
from django.core.cache import cache
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Avg, Case, Count, F, Max, Min, Prefetch, Q, Sum, When
from django.utils import timezone
from django.urls import reverse
from django.db.models import Exists, OuterRef, Subquery

use this parameter to print SQL

$ python manage.py shell_plus --print-sql
>>> Student.objects.all()
SELECT "polls_student"."id",
 "polls_student"."name",
 "polls_student"."age"
 FROM "polls_student"
 LIMIT 21
Execution time: 0.000413s [Database: default]
<QuerySet []>

There are so many other parameters available with this command; please check it out; it will be helpful to understand the query performance.

➡️ show_urls

This will display all the URLs in our project

$ python manage.py show_urls
/admin/ django.contrib.admin.sites.index admin:index
/admin/<app_label>/ django.contrib.admin.sites.app_index admin:app_list
/admin/<url> django.contrib.admin.sites.catch_all_view
............
............

3. Custom Django management commands.

None
Custom Django management commands

We can create custom Django management commands; the folder structure needs to be exactly like this: app → management →commands → file. sample.py is my new management command.

None

Here sample.py is our command; however, if we add an underscore before the file name, like _example.py, then this example command will not be available as a management command.

To consider the smaple.py module as the management command, the only requirement is that it must define a class Command that extends BaseCommand or one of its

sample.py module

from django.core.management.base import BaseCommand
class Command(BaseCommand):
    help = "My shiny new management command."
    def handle(self, *args, **options):
        print("my new command")

The handle method is the entry point to execute the script and our sample command is ready, Let me execute this command

$ python manage.py sample
my new command

When we executed the sample command, our print statement was executed from the handle method. this means our custom management command is working fine,

Now let me pass named arguments to the handle method using the add_arguments(self, parser) method, and this argument we usually pass when we execute the command.

from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = "My shiny new management command."

    def add_arguments(self, parser):
        parser.add_argument(
            "--name", help="any string", default="boss"
        )

    def handle(self, *args, **options):
        print(f"hi {options['name']}")

I overrided the add_argumentsto pass dynamic values to my script with a key name. Let me execute the modified module.

$ python manage.py sample
hi boss

it prints "hi boss", The boss value is coming from the default value from the add_argument method.

$ python manage.py sample --name=hemanth
hi hemanth

Now it printed "hi hemanth" because I passed hemanth as value.

Note: parser.add_arguments supports many useful arguments like action, dest, help, default, etc.

  • for example, let me make use of the dest parameter.
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = "My shiny new management command."

    def add_arguments(self, parser):
        parser.add_argument(
            "--name", help="any string", default="boss", dest="my_name"
        )

    def handle(self, my_name, *args, **options):
        print(f"hi {my_name}")

In the above code, I added the dest keyword argument to the add_argument method, which means we can use the dest value as one of the first parameters in the handle method.

Instead of print statements, we can use something like this for better readability

def handle(self, my_name, *args, **options):
    self.stderr.write(f"hi {my_name}")
    self.stdout.write(self.style.MIGRATE_HEADING(f"hi {my_name}"))
$ python manage.py sample
None

Final thoughts ☑️

The Django management command is such a powerful utility tool. We can use this as a simple Django script for more advanced scripts, and we explored different ways of integrating and writing custom commands. I hope this article gives some ideas to explore the management commands, and if you have any further questions, please add them in the space provided below.

Let's clap.

Still, most commands that we did not discuss here are briefly explained in Django documents; please have a look.

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you go: