Extend the startapp manage command for better Django template apps

Posted by Harald Nezbeda on Fri 02 December 2022

Introduction

The Django startapp management command is a great tool to create new Django apps. By default you can create a new app with the following command:

python manage.py startapp myapp

This will create a new app, based on the internal default template, with the following structure:

    myapp/
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

This is a good start, but this can be done better, especially when the project is going to use additional libraries such as Django Rest Framework or the development team agrees on a common structure for the models, views, urls, etc.

The startapp command also provides the --template option. This option allows you to specify a custom template for the new app. The template can be a directory or a zip file, the zip file can also be provided via URL.

Examples:

# create a new app using a local template
python manage.py startapp --template=/Users/nezhar/django-app-template myapp

# create a new app using a remote template
python manage.py startapp --template=https://github.com/nezhar/django-app-template/archive/main.zip myapp

The problem

The problem with the startapp command is that it is limited to the context parameters that are available in the template, which currently are app_name, app_directory, camel_case_app_name, docs_version and django_version.

This makes it impractical to use the command with advanced templates where additional parameters are required.

In my case, I required certain value configured in the Django settings. I also had use cases where it would have been useful to add parameters when calling the startapp command.

Solution

It seems that there was a ticket to add a similar option in the past, but it was not accepted.

For now, this needs to be solved at application level by creating a custom management command that extends the startapp command with additional parameters.

The implementation of the command can be found here

In our command we can now directly add keyword arguments to pass in options (e.g. app_slug) or additional parameters inside the add_arguments method.

from django.core.management.templates import TemplateCommand
from django.conf import settings


class Command(TemplateCommand):
    help = (
        "Creates a Django app directory structure for the given app name in "
        "the current directory or optionally in the given directory."
    )
    missing_args_message = "You must provide an application name."

    def handle(self, **options):
        app_name = options.pop("name")
        target = options.pop("directory")
        options.update({"app_slug": settings.APP_SLUG})
        super().handle("app", app_name, target, **options)

    def add_arguments(self, parser):
        super().add_arguments(parser)
        parser.add_argument(
            "--custom-option",
            help="Custom option to be used in template context.",
        )

You should use a different name for the command, e.g. startapp2, createapp, etc. to avoid conflicts with the default startapp command.

Conclusion

The startapp command is a great tool to create new Django apps. However, since inside the template you have limited access to the context parameters, you need to extend the command to add additional parameters.