How To Create Custom Management Commands in Django

When developing applications using the Django framework, we extensively use various Django commands like

  • python manage.py runserver
  • python manage.py makemigrations
  • python manage.py migrate

These commands are built-in and lie within Django itself.

Invoking python manage.py or python manage.py help will show all registered commands grouped by app.

Output :

Available subcommands:[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[default]
create_user
run_seeder
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
[django_mysql]
cull_mysql_caches
dbparams
fix_datetime_columns
mysql_cache_migration
[oauth2_provider]
cleartokens
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver

We can also write and register our own management commands and include them in the list. For that, we have to create management/commands directory inside an app directory, like below:

mysite/                                    
|-- core/
| |-- management/
| | +-- commands/
| | +-- custom_command.py
| | +-- __init__.py
| |-- migrations/
| | +-- __init__.py
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- models.py
| |-- tests.py
| +-- views.py
|-- mysite/
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| |-- wsgi.py
+-- manage.py

Here, The name of the file is custom_command.py. So custom_command is added to Django’s command list. We will be able to execute it via

python manage.py custom_command

Let’s explore how to implement custom commands in detail with examples.

Basic Example

Let’s create a send_mail.py file.

The handle method contains the core command logic and is automatically run when invoking the command. The handle method declares three input argument: self to reference the class instance; *args to reference arguments of the method itself; and **kwargs to reference arguments passed as part of the management command.

This custom command can be called using

python manage.py send_mail

Accepting arguments

To handle arguments in our custom command, we need to implement the add_arguments() method.

Let’s consider we have a total three types of roles in our application: superadmin, admin, and staff. We want to create users using the create_users command by sending two arguments :

  1. role_type: Indicate name of roles like staff, admin, or superadmin(mandatory argument)
  2. number_of_users: Indicates how many users we want to create(Optional argument which has 1 as default value)

The add_arguments() method must define a task's arguments, including their type, default value, and help message, among other things. In essence, the add_arguments() method works as a pre-processor to command arguments, which are then made available in the **kwargs argument of the handle() method.

In our example, we declare both a positional and an optional argument. Both arguments are added to the parser.add_argument() method. The difference being, optional arguments use leading dashes -- and if omitted, then an argument is assumed to be positional.

Positional arguments by definition are required. So in this case, the role_type argument is expected otherwise Django throws 'too few arguments' errors.

Optional arguments are not compulsory. Here, number_of_users is not mandatory and it declares 1 as a default value.

Example usage:

python manage.py create_users superadmin

This command will create one superadmin in our application.

If we want to create n number of users, we can do that via

python manage.py create_users staff 10

This will create 10 users who have staff as role_type

Running management commands from code

In some situations, we have to run management commands from code instead of the terminal. The call_command() allows us to invoke a management command from code.

Scheduled Management commands

There are many use cases like

  • We have a web scraper that collects data from some Website every 30 minutes and store data in a database
  • We want to send user’s report mail to our marketing team daily
  • The development team gets error logs data of the production server every Monday

where we want to run custom management commands at scheduled intervals of time such as daily, every Monday, monthly, etc. This can be done by periodically executing the management command from the UNIX crontab or from Windows scheduled tasks control panel.

The example above will execute the send_mail every midnight.

If you have any questions or suggestions, please feel free to leave them in the responses below! Thanks for your time!

A passionate Software Engineer having experience of building Web and Mobile applications with Django,Laravel,Nodejs and some other cool libraries and frameworks

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store