Write Custom Commands for Django

Something very useful I’ve found while using Django is writing custom Django-admin commands for your manage.py. Essentially this is just appending arguments to the CLI of manage.py. You might wonder why can’t you just make your own script in like a folder called project_name/utils/, but you would need to jump through a lot of hoops to use the resources in your Django app in order to do so. If you want to just take a look at the docs instead, you can find it here.

Blog Updater

Here’s a pretty useful example: say you wanted to update the blogs on your site that comes from Medium. We can write a custom manage.py command and use a crontab on the server to run it at any interval you want it to be. Here’s the file structure we will need:

project_name/blogs/
__init__.py
management/
commands/
_private.py
updateblogs.py
models.py
views.py
urls.py

So what we are doing is adding management/commands/ folders into our blogs app in our project, and then adding an empty _private.py file into the commands/ folder. These are the base folders and files you need in order for manage.py to recognize your custom script. updateblogs.py is our custom script, and it will be used like this: python manage.py updateblogs . The filename without the .py extension becomes the argument.

Command Code Structure

There is a basic format of what we need to create a custom manage.py command. Again, you can reference off the docs here, if there is something else you want to do aside from this example.

# project_name/blogs/management/commands/updateblogs.py
"""
Manual medium blog updater
Run crontab to automate
"""
import feedparser
from django.core.management.base import BaseCommand
from blog.models import Blog
class Command(BaseCommand):
help = "Updates blogs"
def handle(self, *args, **options):
rss = feedparser("https://medium.com/feed/username")
blogs = Blog.objects.all()
for b in blogs:
# update all blog objects from rss
b.save()
self.stdout.write(self.style.SUCCESS(f"updated blog_id: {b.id}"))

The string in the help attribute will be shown when running python manage.py filename -h , like shown below.

> /project_name$ python manage.py medium -h
usage: ...
Updates blogs
...

All logic is handled in the handle() function. And you can use the self.stdout.write command, along with the self.style attributes to write colored print messages. You can see below how our updateblogs.py would run according to our example code from above.

> /project_name$ python manage.py medium
updated blog_id 0
updated blog_id 1
updated blog_id 2
>

You can use crontab to automate this script in order to run with a venv:

#!/usr/bin/env bash
source ~/project_name/venv/bin/activate
python ~/project_name/manage.py medium

There are a lot more other use cases for writing custom commands in Django, let me or others know what you have used them for in the comments below.

Software Engineer living in Tokyo | Linux | Cats | https://github.com/kai-dg | https://haruspace.dev | https://ko-fi.com/harukai