Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Custom Django Management Commands

  • Difficulty Level : Basic
  • Last Updated : 06 Aug, 2021

Prerequisites:  Django Introduction and Installation

Manage.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 startapp
  • python manage.py makemigrations
  • python manage.py migrate
  • python manage.py runserver

Interestingly 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 Started

Follow Django Introduction and Installation to setup a virtual environment and install Django

Step 1: Initialize a project by following command

django-admin startproject geeks_site

Step 2: Create an app named blog

python manage.py startapp blog

Step 3: Add your app to the settings.py

In geeks_site/settings.py

Python3




# Application definition
  
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 app

Model Article :

  • Fields :
    • title: Stores the title of an article
    • body: Content of that article
    • created_on: Date and Time on which that article was created

Model Comment :

  • Fields :
    • article:  Article on which comment is created
    • text: Actual comment
    • created_on: Date and Time on which that article was created
    <

    In blog/models.py

    Python3




    from 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.py

    Python3




    from 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 terminal

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

    Create a superuser account to log in to the admin panel

    python manage.py createsuperuser

    Now, 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 Commands

    • Add a management/commands directory to the blog app
    • Add __init__.py to blog/management and __init__.py + stats.py files to blog/management/commands directory

    Note: Django will register a manage.py command for each Python module in that directory whose name doesn’t begin with an underscore

    The 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.py

    Python3




    from django.core.management.base import BaseCommand
    from django.db.models import Count
    from blog.models import Article, Comment
    from datetime import timedelta, datetime
    from 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 file

    Basically, a Django management command is built from a class named Command which inherits from BaseCommand.

    1) help: It tells what actually the command does.

    the following command and see the help
    python manage.py stats --help

    2) handle(): It handles all the logic which needs to be executed when the command is executed. Let’s understand of code inside handle() method

    • Here we are concerned about the following two stats
      • Number of articles which were published in last 5 hours
      • Number of  comments created in last 5 hours per article
    • From: Current time – 5 hours
    • To: Current Time
    • articles_published_in_last_5_hour : an integer value
    • comments_published_per_article :  queryset object or a list of dictionaries
    • print statements to output data on terminal

    Now, Run the following command in your terminal :

    python manage.py stats

    Output : 

    Adding Arguments

    Django uses the argparse module to handle the custom arguments. We need to define a function add_arguments under the command class to handle arguments.

    Python3




    from django.core.management.base import BaseCommand
    from django.db.models import Count
    from app.models import Article, Comment
    from datetime import timedelta, datetime
    from 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:


    My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!