How To Build Custom Django Management Commands

·

12 min read

Django has a lot of commands built in, In this article, we will be building our own custom Django Management Commands. Before we proceed, I'll have to set-up some basic commands that we can easily execute from the terminal. Another important thing to know before proceeding is knowing where to store our management commands. To do this, we create a new project and call it "proj", and a new application and call it "app". Now in terms of storage, " the management commands" are stored inside of the "application" inside of a folder that is called "management" in a sub folder called "commands".

So to build this command, we open command prompt and input

(venv) c:\proj>py manage.py nameofcommand

There are basically two types of commands that can be built, namely;

  1. A private command(_private.py)
  2. A non-private command(not private.py) which can be run from the terminal. A private command is made when it comes to instances where an application is needed to run a command from the manage py, while the non private command can be run from the command line. Finally getting started, we'll be building a simple command using Visual Studio. To do this, we first of all create a new file and name it, in my case, mine will be called namegen.py. After this, we need to define a class which is called command and that will extend the base command. Now, we import the base command;
    from django.core.management.base import BaseCommand
    
    Then a random string is created, in this case imported
    from django.utils.crypto import get_random_string
    
    And a class command by extending from the base command
    class Command(BaseCommand):
    
    A help documentation is added to show in the help function by creating a variable help,
    python help function - display the documentation
    help = 'Elon Musk baby name generator'
    
    A function is then created,
    def handle(self, *args, **kwargs):
    
    Within this function a random string is gotten, which will be placed in a variable name,
             name =
    get_random_string(length=32)
             self.stdout.write(name)
    

So then the entire input will look like this;

from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):

python help function - display the documentation
help = 'Elon Musk baby name generator'

def handle(self, *args, **kwargs):
               name = get_random_string(length=32)
               self.stdout.write(name)

After this, we register the app in the settings file so that the commands can work without any issues. We now move to the terminal which is command prompt, where the string (Elon Musk baby name generator') will be tested, we input

(venv) c:\proj>py manage.py namegen

After inputing and running we then get, something like this,

(venv) c:\proj>py manage.py namegen
XLXA2RfBD7sQ6nvQ7OrXjiYyTeo4RBa3

Then to build a custom command, first we import the user database,

from django.contrib.auth.models import user

Then extend from base command,

from django.core.management.base import BaseCommand

Then import random string,

from django.utils.crypto import get_random_string

Input the mandatory class command, then extend from base command,

class Command(BaseCommand):

Setup help text,

help = 'Database random user generator'

Then set up new argument,

def add_arguments(self,parser):

Note here that we've not used an argument in the last command we built, so this is a new one which can be parsed after we've set up the command that's in the terminal. It is defined as shown below,

              parser.add_argument('qty', type=int, help='The amount of users to create')

Next, a new function is set up

def handle(self, *args, **kwargs):
       qty = kwargs['qty']

A loop is then run for this to get random string for a username and a password,

       for i in range(qty):
             username = get_random_string(10)
             password = get_random_string(10)

This is put into the database using the objects,

             User.objects.create_user(username=username, email=' ', password=password)

So then overall command will look like this;

from django.contrib.auth.models import user
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):
help = 'Database random user generator'

def add_arguments(self,parser):         
              parser.add_argument('qty', type=int, help='The amount of users to create')

def handle(self, *args, **kwargs):
       qty = kwargs['qty']

       for i in range(qty):
             username = get_random_string(10)
             password = get_random_string(10)

             User.objects.create_user(username=username, email=' ', password=password)

After inputing, we then go to the terminal to run the command. The name of the command in this case is usergen.py and also we include the number of users we are going to parse, in my case I'll use 2. So to run the command we input,

(venv) c:\proj>py manage.py usergen 2

After inputing, we let it run and the result is shown in the database to have created two random users. Going back into the workspace, we create what is called a "std out" to write a username and password that has been generated and an account created, and we add it to our already written code. The code is shown below,

self.stdout.write('User "%s (%s)" account created! ' % (username, password)

The entire cod is then run on the terminal to give a result,

(venv) c:\proj>py manage.py usergen 2
User "Hnc72IEGzv (X3j7KzPrz0)" account created!
User "Lz7sQPWQNK (KdgbdLuwgz)" account created!

The results given are the names of the users that were built.

Now,the next thing we'll be looking at is how to generate an administrator account. The procesure is as follows, first we input this code that we've used before;

from django.contrib.auth.models import user
from django.core.management.base import BaseCommand
from django.utils.crypto import get_random_string

class Command(BaseCommand):
help = 'Database random user generator'

def add_arguments(self,parser):

We add a positional argument,

              parser.add_argument('qty', type=int, help='The amount of users to create')

Then we add a new argument which will define an admin account,this is called a flag argument

parser.add_argument('-a', '--admin', action='store_true', help='Define an admin account')

Next we add the function,

def handle(self, *args, **kwargs):
       qty = kwargs['qty']
       admin = kwargs['admin']

Then we loop and create a random username and password,

       for i in range(qty):
             username = get_random_string(10)
             password = get_random_string(10)

Next, if admin has been defined, we create a super user with "if" using the random string, then we create a normal user with "else",

if admin:
     User.objects.create_superuser(username=username, email=' ', password=password)
else:
     User.objects.create_user(username=username, email=' ', password=password)

Then we add the "stdout" and run the entire code in the terminal,

self.stdout.write('User "%s (%s)" account created! ' % (username, password)

When we run the code in the terminal,

(venv) c:\proj>py manage.py usergen 2 -a

Note that "-a" is the flag argument So the result will be with two new users created,

(venv) c:\proj>py manage.py usergen 2 -a
User "BKv9mB18hu (R32zNDKS2r)" account created!
User "k5bkHPmckt (t8zNB42nMU)" account created!

On the Django administration website, we refresh and it is updated that 2 new users have been created. Next, we'll look at how to delete users from a database. We'll create a new file, in my case I'll call the file "userdel". Then we import the users model and base command,

from django.contrib.auth.models import user
from django.core.management.base import BaseCommand

Then we input the class command,

class Command(BaseCommand):

Next, we include the help text,

help = 'Used to delete users or users from database'

Then add a new argument,

def add_arguments(self, parser):
       parser.add_argument('user_id', nargs='+', type=int, help='User ID')

After the argument, we create a new function,

       def handle(self, *args, **kwargs):
              users = kwargs['user_id']

Then a single loop is included, which will be used when there are multiple users. The deletion of these users will be done through the user IDs which are inputed in the terminal,

          for user_id in users:
                try:
                     user = User.objects.get(pk=user_id)
                     user.delete()

After this, we'll output that the user have been deleted with the code as shown below,

                     self.stdout.write(' "%s (%s)" has been deleted!' % (user.username, user_id))

And if the user does not exist, we'll output that they do not exist in the database with the code as shown below,

               except User.DoesNotExist:
                        self.stdout.write('User "%s" does not exist in the database' % user_id)

After inputing, we'll go to the terminal to try out our codes. To do this, we input,

(venv) c:\proj>py manage.py userdel 5 6 7

Note that the numbers 5, 6, and 7 are my own user IDs. So you can use yours and have your own results. So the result is given as,

(venv) c:\proj>py manage.py userdel 5 6 7
user "t" does not exist in the database
user "6" does not exist in the database
"LCI1sf80nS (7)" has been deleted!

If we were to go back to our browser and refresh, we'll see that the number indicated in the terminal to have been deleted, has taken effect there also. This means our code worked!