Custom Django Management Commands

Prerequisites:  Django Introduction and InstallationManage.py in Django is a command-line utility that works similar to the django-admin command. The difference is that it points towards the project’s settings.py file. This manage.py utility provides various commands that you must have while working with Django. Some of the most commonly used commands are –python manage.py startapppython manage.py makemigrationspython manage.py migratepython manage.py runserverInterestingly we can create our own Custom Management Commands to fulfill a wide variety of requirements ranging from interacting with our application using the command line to serve as an interface to execute Cron Jobs. We are going to create a custom Management Command which gives us the stats or metrics of new articles published, comments on those articles on a particular day.Getting StartedFollow Django Introduction and Installation to setup a virtual environment and install DjangoStep 1: Initialize a project by following commanddjango-admin startproject geeks_siteStep 2: Create an app named blogpython manage.py startapp blogStep 3: Add your app to the settings.pyIn geeks_site/settings.pyPython3  INSTALLED_APPS = [    ‘django.contrib.admin’,    ‘django.contrib.auth’,    ‘django.contrib.contenttypes’,    ‘django.contrib.sessions’,    ‘django.contrib.messages’,    ‘django.contrib.staticfiles’,      ‘blog’,]Step 4: Create Models named Article and Comment in the blog appModel Article :Fields :title: Stores the title of an articlebody: Content of that articlecreated_on: Date and Time on which that article was createdModel Comment :Fields :article:  Article on which comment is createdtext: Actual commentcreated_on: Date and Time on which that article was createdIn blog/models.pyPython3from django.db import models    class Article(models.Model):    title = models.CharField(max_length=200)    body = models.TextField()    created_on = models.DateTimeField(auto_now_add=True)    class Comment(models.Model):    article = models.ForeignKey(Article, on_delete=models.CASCADE)    text = models.CharField(max_length=200)    created_on = models.DateTimeField(auto_now_add=True)Step 5: Register your model in blog/admin.py so that it shows up in the admin panel.In blog/admin.pyPython3from django.contrib import admin from .models import Article, Comment    admin.site.register(Article)admin.site.register(Comment)Step 6: Now, To migrate all your changes and start the server, run the following commands in your terminalpython manage.py makemigrations
python manage.py migrate
python manage.py runserverCreate a superuser account to log in to the admin panelpython manage.py createsuperuserNow, Visit the admin panel at http://127.0.0.1:8000/admin/ Create some articles and then some comments : Now, Let’s start working on the creation of Custom Django Management CommandsAdd a management/commands directory to the blog appAdd __init__.py to blog/management and __init__.py + stats.py files to blog/management/commands directoryNote: Django will register a manage.py command for each Python module in that directory whose name doesn’t begin with an underscoreThe folder structure of the blog app looks like this : We will use python manage.py stats to run our custom management command. Now we will configure what actually this command will do.In stats.pyPython3from django.core.management.base import BaseCommandfrom django.db.models import Countfrom blog.models import Article, Commentfrom datetime import timedelta, datetimefrom django.utils.timezone import utc    def now():    return datetime.utcnow().replace(tzinfo=utc)    class Command(BaseCommand):    help = ‘Displays stats related to Article and Comment models’      def handle(self, *args, **kwargs):        From = now() – timedelta(hours=5)        To = now()          articles_published_in_last_5_hour = Article.objects.filter(            created_on__gt=From, created_on__lte=To).count()        comments_published_per_article = Comment.objects.filter(            created_on__gt=From, created_on__lte=To).values(          ‘article’).annotate(count=Count(‘article’)).order_by()          print(“Articles Published in last 5 hours = “,              articles_published_in_last_5_hour)                  print(“Comments per Article in last 5 hours”)        for data in comments_published_per_article:            print(data)Understanding the stats.py fileBasically, a Django management command is built from a class named Command which inherits from BaseCommand.1) help: It tells what actually the command does. Run the following command and see the helppython manage.py stats –help2) handle(): It handles all the logic which needs to be executed when the command is executed. Let’s understand of code inside handle() methodHere we are concerned about the following two statsNumber of articles which were published in last 5 hoursNumber of  comments created in last 5 hours per articleFrom: Current time – 5 hoursTo: Current Timearticles_published_in_last_5_hour : an integer valuecomments_published_per_article :  queryset object or a list of dictionariesprint statements to output data on terminalNow, Run the following command in your terminal :python manage.py statsOutput :  Adding ArgumentsDjango uses the argparse module to handle the custom arguments. We need to define a function add_arguments under the command class to handle arguments.Python3from django.core.management.base import BaseCommandfrom django.db.models import Countfrom app.models import Article, Commentfrom datetime import timedelta, datetimefrom django.utils.timezone import utc    def now():    return datetime.utcnow().replace(tzinfo=utc)  class Command(BaseCommand):    help = ‘Displays stats related to Article and Comment models’      def add_arguments(self, parser):        parser.add_argument(‘-t’, ‘–time’, type=int, help=’Articles published in last t hours’)      def handle(self, *args, **kwargs):        t = kwargs[‘time’]        if not t:            t=5        From = now() – timedelta(hours=t)        To = now()          articles_published_in_last_t_hour = Article.objects.filter(            created_on__gt=From, created_on__lte=To).count()                  comments_published_per_article = Comment.objects.filter(            created_on__gt=From, created_on__lte=To).values(            ‘article’).annotate(count=Count(‘article’)).order_by()          print(f”Articles Published in last {t} hours = “,              articles_published_in_last_t_hour)          print(f”Comments per Article in last {t} hours”)        for data in comments_published_per_article:            print(data)Output:  Attention geek! Strengthen your foundations with the Python Programming Foundation Course and learn the basics.  To begin with, your interview preparations Enhance your Data Structures concepts with the Python DS Course. And to begin with your Machine Learning Journey, join the Machine Learning – Basic Level Course