15. Management Commands

15.1. Built-in

[auth]
    changepassword
    createsuperuser

[contenttypes]
    remove_stale_contenttypes

[dashboard]
    customdashboard

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver

[sessions]
    clearsessions

[staticfiles]
    collectstatic
    findstatic
    runserver

15.2. Writing own management commands

15.2.1. Structure

app
    management
    __init__.py
        commands
        __init__.py
        my_command.py

15.2.2. Minimal command boilerplate code

from django.core.management.base import BaseCommand


class Command(BaseCommand):
    help = 'What my command does?'

    def handle(self, *args, **options):
        pass

15.2.3. Cleaning data in database

from django.core.management.base import BaseCommand
from ksiazkaadresowa.models import Person


class Command(BaseCommand):
    help = 'Clean data in database'

    def handle(self, *args, **options):
        for p in Person.objects.all():
            p.first_name = p.first_name.title()
            p.last_name = p.last_name.title()
            p.save()

15.2.4. Parse file line by line

from django.core.management.base import BaseCommand
from ksiazkaadresowa.models import Person


class Command(BaseCommand):
    help = 'Moj tekst pomocy'

    def add_arguments(self, parser):
        parser.add_argument(
            '--file',
            dest='file',
            nargs='?',
            help='Log File',
        )

        parser.add_argument(
            '--format',
            nargs='?',
            dest='format',
            help='Log File Format',
        )

    def parse_line(self, line, format):
        if format == 'text':
            return line.upper()

    def handle(self, *args, **options):
        filename = options['file']
        format = options['format']
        content = []

        with open(filename, encoding='utf-8') as file:
            for line in file:
                line = self.parse_line(line, format)
                content.append(line)

        print('\n'.join(content))

15.2.5. Case Study

Code Listing 15.1. Writing own management commands
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll


class Command(BaseCommand):
    help = 'Closes the specified poll for voting'

    def add_arguments(self, parser):
        parser.add_argument('poll_id', nargs='+', type=int)
        parser.add_argument(
            '--delete',
            action='store_true',
            dest='delete',
            help='Delete poll instead of closing it',
        )

    def handle(self, *args, **options):

        for poll_id in options['poll_id']:
            try:
                poll = Poll.objects.get(pk=poll_id)
            except Poll.DoesNotExist:
                raise CommandError('Poll "%s" does not exist' % poll_id)

            if options['delete']:
                return self.delete_poll(poll)
            else:
                return self.close_poll(poll)

    def close_poll(self, poll):
        poll.opened = False
        poll.save()
        self.stdout.write(self.style.SUCCESS('Successfully closed poll "{poll.pk}"'))

    def delete_poll(self, poll):
        poll.delete()