Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to automate createsuperuser on django?

Tags:

django

People also ask

What is Django Createsuperuser?

Django provides us Admin Panel for it's users. So we need not worry about creating a separate Admin page or providing authentication feature as Django provides us that feature. Before using this feature, you must have migrated your project, otherwise the superuser database will not be created.


If you reference User directly, your code will not work in projects where the AUTH_USER_MODEL setting has been changed to a different user model. A more generic way to create the user would be:

echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'password')" | python manage.py shell

ORIGINAL ANSWER

Here there is a simple version of the script to create a superuser:

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | python manage.py shell

As of Django 3.0 you can use default createsuperuser --noinput command and set all required fields (including password) as environment variables DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAIL for example. --noinput flag is required.

This comes from the original docs: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-createsuperuser

It is the most convenient way to add createsuperuser to scripts and pipelines.


I was searching for an answer to this myself. I decided to create a Django command which extends the base createsuperuser command (GitHub):

from django.contrib.auth.management.commands import createsuperuser
from django.core.management import CommandError


class Command(createsuperuser.Command):
    help = 'Crate a superuser, and allow password to be provided'

    def add_arguments(self, parser):
        super(Command, self).add_arguments(parser)
        parser.add_argument(
            '--password', dest='password', default=None,
            help='Specifies the password for the superuser.',
        )

    def handle(self, *args, **options):
        password = options.get('password')
        username = options.get('username')
        database = options.get('database')

        if password and not username:
            raise CommandError("--username is required if specifying --password")

        super(Command, self).handle(*args, **options)

        if password:
            user = self.UserModel._default_manager.db_manager(database).get(username=username)
            user.set_password(password)
            user.save()

Example use:

./manage.py createsuperuser2 --username test1 --password 123321 --noinput --email '[email protected]'

This has the advantage of still supporting the default command use, while also allowing non-interactive use for specifying a password.


I use './manage.py shell -c':

./manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'adminpass')"

This doesn't uses an extra echo, this has the benefit that you can pass it to a docker container for execution. Without the need to use sh -c "..." which gets you into quote escaping hell.

And remember that first comes username, then the email.

If you have a custom user model you need to import that and not auth.models.User


I would suggest running a Data Migration, so when migrations are applied to the project, a superuser is created as part of the migrations. The username and password can be setup as environment variables. This is also useful when running an app in a container (see this thread as an example)

Your data migration would then look like this:

import os
from django.db import migrations

class Migration(migrations.Migration):
    dependencies = [
        ('<your_app>', '<previous_migration>'),
    ] # can also be emtpy if it's your first migration

    def generate_superuser(apps, schema_editor):
        from django.contrib.auth.models import User

        DJANGO_SU_NAME = os.environ.get('DJANGO_SU_NAME')
        DJANGO_SU_EMAIL = os.environ.get('DJANGO_SU_EMAIL')
        DJANGO_SU_PASSWORD = os.environ.get('DJANGO_SU_PASSWORD')

        superuser = User.objects.create_superuser(
            username=DJANGO_SU_NAME,
            email=DJANGO_SU_EMAIL,
            password=DJANGO_SU_PASSWORD)

        superuser.save()

    operations = [
        migrations.RunPython(generate_superuser),
    ]

Hope that helps!

EDIT: Some might raise the question how to set these environment variables and make Django aware of them. There are a lot of ways and it's been answered in other SO posts, but just as a quick pointer, creating a .env file is a good idea. You could then use the python-dotenv package, but if you have setup a virtual environment with pipenv, it will automatically set the envvars in your .env file. Likewise, running your app via docker-compose can read in your .env file.