Search code examples
pythondjangobashdjango-users

How to create a Django superuser if it doesn't exist non-interactively?


I want to automate creation of Django users via a Bash script. I found this snippet which almost suits my needs:

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

How can I modify it so that it's a nop if the user already exists?


Solution

  • Using manage.py shell

    You can use the QuerySet API methods to check if a user exists, and then create it if it doesn't. Also, it may be easier to put the code in a heredoc:

    cat <<EOF | python manage.py shell
    from django.contrib.auth import get_user_model
    
    User = get_user_model()  # get the currently active user model,
    
    User.objects.filter(username='admin').exists() or \
        User.objects.create_superuser('admin', '[email protected]', 'pass')
    EOF
    

    Using a custom management command

    Another, more maintainable option is to add a custom management command for your Django app. Adapting the example from the docs, edit yourapp/management/commands/ensure_adminuser.py to look like this:

    import os
    from django.contrib.auth import get_user_model
    from django.core.management.base import BaseCommand
    
    class Command(BaseCommand):
        help = "Creates an admin user non-interactively if it doesn't exist"
    
        def add_arguments(self, parser):
            parser.add_argument('--username', help="Admin's username")
            parser.add_argument('--email', help="Admin's email")
            parser.add_argument('--password', help="Admin's password")
            parser.add_argument('--no-input', help="Read options from the environment",
                                action='store_true')
    
        def handle(self, *args, **options):
            User = get_user_model()
    
            if options['no_input']:
                options['username'] = os.environ['DJANGO_SUPERUSER_USERNAME']
                options['email'] = os.environ['DJANGO_SUPERUSER_EMAIL']
                options['password'] = os.environ['DJANGO_SUPERUSER_PASSWORD']
    
            if not User.objects.filter(username=options['username']).exists():
                User.objects.create_superuser(username=options['username'],
                                              email=options['email'],
                                              password=options['password'])
    

    Then you can call the new custom command from your Bash script like this:

    python manage.py ensure_adminuser --username=admin \
        [email protected] \
        --password=pass