What is the purpose of "_private.py" file when making custom management commands in Django?

Viewed 408

Hi guys I have been trying to find a reason for the existence of the _private.py file when you are declaring custom management commands. I tried to look on many pages and forums and I did not find anything relevant.

The most explicit documentation about this file that I found, is on the official documentation which states the following:

The _private.py module will not be available as a management command.

However that really does not give us so much information about what is the purpose of that file, or why would I really need to declare that, does any one of you guys know?

2 Answers

The name _private.py isn't a special, but its leading underscore is (from the link in your question, bold added):

To do this, add a management/commands directory to the application. Django will register a manage.py command for each Python module in that directory whose name doesn’t begin with an underscore.

As to why you'd want a file there that doesn't get registered as a command, maybe you want to factor out some behaviour and use it in two modules that do get registered as commands.

I recently asked myself the same question because I was wondering if I could use this file to add code which could be shared for all my custom commands.

From this link, I found that I could create a subclass of BaseCommand in order to provide utility functions for my other commands.

Here's how I did it :

_private.py

from abc import ABC
from smtplib import SMTPException

from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.core.management import BaseCommand


class SendMailBaseCommand(BaseCommand, ABC):
    def send_mail(self, to: list, subject: str, txt_content: str, html_content: str = None):
        msg = EmailMultiAlternatives(
            subject=subject,
            body=txt_content,
            from_email=settings.DEFAULT_FROM_EMAIL,
            to=to
        )
        if html_template:
            msg.attach_alternative(html_content), 'text/html')
        try:
            msg.send()
        except SMTPException as e:
            self.stdout.write(f'There was an error when sending email : {e}')
        else:
            self.stdout.write('Mail sent !')

Then I can import SendMailBaseCommand in my other custom commands in order have access to this send_mail utility function.

my_custom_command.py

from hibou.management.commands._private import SendIpexiaMailBaseCommand


class Command(SendMailBaseCommand):
    help = 'Test command to show how to use the send_mail function'

    def handle(self, *args, **options):
        self.send_mail(
            to=['test@mail.com'],
            subject='Test subject',
            txt_content='Text content',
            html_content='<h1>HTML part</h1>'
        )
Related