¿Cómo automatizar createuperuser en django?

128

Quiero ejecución automática manage.py createsuperuseren djangopero las costuras que no hay forma de establecer una contraseña por defecto.

¿Cómo puedo conseguir esto? Tiene que ser independiente de la base de datos de django.

bogdan
fuente
1
¿Ha pensado en guardar un dispositivo de su superusuario creado y cargarlo usando manage.py?
turbotux
1
@turbotux La respuesta de Hendrik F adopta un enfoque similar a lo que sugiere, con la capacidad adicional de leer los valores (inicio de sesión, contraseña ...) de env vars (o sistema de archivos, ...). Sugeriría encarecidamente ir en esta dirección en lugar de los scripts de python ad-hoc, que tienen problemas cuando reinicia la aplicación.
Anuncio N

Respuestas:

145

Si hace referencia a User directamente, su código no funcionará en proyectos donde la configuración AUTH_USER_MODEL se haya cambiado a un modelo de usuario diferente. Una forma más genérica de crear el usuario sería:

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

RESPUESTA ORIGINAL

Aquí hay una versión simple del script para crear un superusuario:

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | python manage.py shell
Tk421
fuente
2
super útil cuando se trata de crear superusuario en heroku y su red bloquea el puerto 5000
Vic
4
Eliminaría el superusuario existente, por lo que esto es válido para cada compilación: echo "from django.contrib.auth.models import User; User.objects.filter(email='[email protected]').delete(); User.objects.create_superuser('[email protected]', 'admin', 'nimda')" | python manage.py shell
Montaro
12
Personalmente, no creo que eliminar al usuario en cada compilación sea una buena idea. Corre el riesgo de eliminar involuntariamente cualquier registro asociado mediante una eliminación en cascada. Una opción más segura es simplemente rescatar si el usuario ya existe (o actualizar el registro de usuario existente).
Will el
6
Al menos en Django 1.11. el orden de los argumentos es ('nombre de usuario', 'correo electrónico', 'contraseña'), no ('correo electrónico', 'nombre de usuario', 'contraseña'). Ver: docs.djangoproject.com/en/1.11/ref/contrib/auth/…
np8
3
from django.contrib.auth.models import Userya no funciona. Utilice esto: from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'my secure password')
dcalde
49

Yo mismo buscaba una respuesta a esto. Decidí crear un comando de Django que amplíe el createsuperusercomando base ( 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()

Ejemplo de uso:

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

Esto tiene la ventaja de que aún admite el uso de comandos predeterminado, al tiempo que permite un uso no interactivo para especificar una contraseña.

Adam Charnock
fuente
4
Esta debería ser la respuesta más votada (y aceptada).
bruno desthuilliers
Desearía que el valor predeterminado también createsuperusertuviera este --passwordcampo
shadi
1
Puede agregar un uso de ejemplo:./manage.py createsuperuser2 --username test1 --password 123321 --noinput --email '[email protected]'
shadi
2
cómo se createsuperuser2asigna a esta clase, función
Srinath Ganesh
2
@SrinathGanesh eche un vistazo a docs.djangoproject.com/en/1.8/howto/custom-management-commands . Debe nombrar el archivo python createsuperuser2.pyy colocarlo en la estructura de directorio definida en el enlace anterior.
ElectRocnic
43

Yo uso './manage.py shell -c':

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

Esto no usa un eco adicional, esto tiene la ventaja de que puede pasarlo a un contenedor docker para su ejecución. Sin la necesidad de usar sh -c "..." lo que te lleva a comillas escapar del infierno.

Y recuerde que primero viene el nombre de usuario, que el correo electrónico.

Si tiene un modelo de usuario personalizado, debe importarlo y no auth.models.User

Yvess
fuente
1
Trabajó para mi. ¡Gracias!
TimH - Codidact
No parece funcionar para mí, estoy viendo:AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'
Brodan
cuando se tiene un modelo de usuario personalizado como users.User lo necesario para la importación de eso y no desdeauth.User
yvess
30

Sugeriría ejecutar una migración de datos , por lo que cuando se aplican migraciones al proyecto, se crea un superusuario como parte de las migraciones. El nombre de usuario y la contraseña se pueden configurar como variables de entorno. Esto también es útil cuando se ejecuta una aplicación en un contenedor (consulte este hilo como ejemplo)

Su migración de datos se vería así:

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_DB_NAME = os.environ.get('DJANGO_DB_NAME', "default")
        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),
    ]

¡Espero que ayude!

EDITAR : Algunos podrían plantear la pregunta de cómo configurar estas variables de entorno y hacer que Django las conozca. Hay muchas formas y se ha respondido en otras publicaciones de SO, pero solo como un indicador rápido, crear un .envarchivo es una buena idea. Luego puede usar el paquete python-dotenv , pero si ha configurado un entorno virtual con pipenv, automáticamente establecerá los envvars en su .envarchivo. Del mismo modo, ejecutar su aplicación a través de docker-compose puede leer en su .envarchivo.

Hendrik F
fuente
1
SUGERENCIA: Considere este enfoque . Esta es una respuesta de alta calidad: naturalmente aprovecha las funcionalidades integradas de Django para responder la pregunta en lugar de hacer eco de los scripts de Python ad-hoc, además, naturalmente, aborda el mayor problema de la respuesta aceptada (una migración se aplica solo una vez en una implementación , por lo que el usuario solo se crea una vez). Funciona maravillosamente en un contexto de contenedor.
Anuncio N
Esta parece una gran respuesta. Todavía no sé en qué parte del proyecto encaja este código.
Pablo Ruiz Ruiz
Debería estar en su carpeta de migraciones, por ejemplo root/⁨mysite⁩/myapp⁩/⁨migrations⁩, si lee los documentos, explica cómo puede crear una migración vacía y modificarlapython manage.py makemigrations --empty yourappname
Hendrik F
¿Por qué necesitas DJANGO_DB_NAME? nunca se usa.
thoroc
Debe mencionar agregar lo siguiente para cargar las vars .env al settings.pyarchivo:python # loading .env from dotenv import load_dotenv from pathlib import Path env_path = Path('.', '.env') load_dotenv(dotenv_path=env_path)
thoroc
23

A partir de Django 3.0 se puede utilizar por defecto createsuperuser --noinputdel sistema y establezca todos los campos requeridos (incluyendo la contraseña) como variables de entorno DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAILpor ejemplo. --noinputSe requiere bandera.

Esto proviene de los documentos originales: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-createsuperuser

y acabo de comprobarlo, funciona. Ahora puede exportar fácilmente esas variables de entorno y agregarlas createsuperusera sus scripts y canalizaciones.

Alexey Trofimov
fuente
14

Podría escribir una secuencia de comandos de Python simple para manejar la automatización de la creación de superusuarios. El Usermodelo es solo un modelo Django normal, por lo que seguiría el proceso normal de escribir un script Django independiente. Ex:

import django
django.setup()

from django.contrib.auth.models import User

u = User(username='unique_fellow')
u.set_password('a_very_cryptic_password')
u.is_superuser = True
u.is_staff = True
u.save()

También puede pasar createsuperuseralgunas opciones, a saber, --noinputy --username, que le permitirían crear automáticamente nuevos superusuarios, pero no podrán iniciar sesión hasta que establezca una contraseña para ellos.

zeekay
fuente
2
Está bien cretesuperuser, pero ¿cómo establecer la contraseña entonces? Me gustaría hacer eso dentro de un script bash ...
caneta
10

Respuesta actual más votada:

  • Elimina al usuario si existe y, como señaló @Groady en los comentarios, corre el riesgo de eliminar involuntariamente cualquier registro asociado a través de una eliminación en cascada.
  • Verifica la existencia de superusuarios filtrando por correo, por lo que si dos superusuarios tienen el mismo correo, Dios sabe cuál borrará.
  • Es complicado actualizar los parámetros del script: nombre de usuario, contraseña y correo.
  • No registra lo que hizo.

Una versión mejorada sería:

USER="admin"
PASS="super_password"
MAIL="[email protected]"
script="
from django.contrib.auth.models import User;

username = '$USER';
password = '$PASS';
email = '$MAIL';

if User.objects.filter(username=username).count()==0:
    User.objects.create_superuser(username, email, password);
    print('Superuser created.');
else:
    print('Superuser creation skipped.');
"
printf "$script" | python manage.py shell
David Darias
fuente
2
Mucho más limpio (mejor) que la respuesta aceptada. También podría haber usado: if not User.objects.filter(username = username).exists(),
Philippe Fanaro
5
DJANGO_SUPERUSER_USERNAME=testuser \
DJANGO_SUPERUSER_PASSWORD=testpass \
python manage.py createsuperuser --noinput

Documentación para el comando createuser

Rafal Enden
fuente
Ésta es la solución más sencilla. Pero puede sobrescribir la noinputbandera con otros parámetros:DJANGO_SUPERUSER_PASSWORD=testpass python manage.py createsuperuser --username testuser --email [email protected] --noinput
dannydedog
1

Usé Tk421 una línea pero recibí un mensaje de error como: 1) Creo que estoy usando una versión posterior de Django (1.10) Manager isn't available; 'auth.User' has been swapped for 'users.User'2) el orden de los parámetros para create_superuser era incorrecto.

Así que lo reemplacé con:

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

y lo que realmente me complació es que también funciona en una implementación de heroku:

heroku run echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.filter(email='[email protected]', is_superuser=True).delete(); User.objects.create_superuser('admin', '[email protected]', 'nimda')" | python manage.py shell

Esto funcionará bien repetidamente. Lo estoy usando al comienzo de un proyecto, así que no se preocupe por las terribles eliminaciones en cascada que podrían ocurrir más adelante.

He vuelto a visitar después de algunos problemas al ejecutar esto dentro de local () desde fabric. lo que parecía estar sucediendo es que el símbolo de la tubería significaba que se estaba interpretando localmente en lugar de heroku. Para ordenar esto, envolví el comando entre comillas. Luego tuvo que usar comillas dobles triples para las cadenas de Python dentro de las comillas simples de todo el comando de Python.

heroku run "echo 'from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.filter(email="""admin@example.com""", is_superuser=True).delete(); User.objects.create_superuser("""admin""", """admin@example.com""", """nimda""")' | python manage.py shell"
hum3
fuente
1

Una solución basada en el enfoque de Adam Charnock anterior ya está disponible como paquete de Python. Toma tres pasos:

  1. Instalar en pc: pip install django-createsuperuserwithpassword

  2. Activar: INSTALLED_APPS += ("django_createsuperuserwithpassword", )

  3. Aplicar:

    python manage.py createsuperuserwithpassword \
            --username admin \
            --password admin \
            --email admin@example.org \
            --preserve

Eso es.

Sebastián
fuente
0

Este pequeño script de Python podría crear un usuario normal o un superusuario

#!/usr/bin/env python

import os
import sys
import argparse
import random
import string
import django


def main(arguments):

    parser = argparse.ArgumentParser()
    parser.add_argument('--username', dest='username', type=str)
    parser.add_argument('--email', dest='email', type=str)
    parser.add_argument('--settings', dest='settings', type=str)
    parser.add_argument('--project_dir', dest='project_dir', type=str)
    parser.add_argument('--password', dest='password', type=str, required=False)
    parser.add_argument('--superuser', dest='superuser', action='store_true', required=False)

    args = parser.parse_args()

    sys.path.append(args.project_dir)
    os.environ['DJANGO_SETTINGS_MODULE'] = args.settings
    from django.contrib.auth.models import User
    django.setup()

    username = args.username
    email = args.email
    password = ''.join(random.sample(string.letters, 20)) if args.password is None else args.password
    superuser = args.superuser 

    try:
        user_obj = User.objects.get(username=args.username)
        user_obj.set_password(password)
        user_obj.save()
    except User.DoesNotExist:
    if superuser:
            User.objects.create_superuser(username, email, password)
    else:
        User.objects.create_user(username, email, password)

    print password


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

--superuser & --password no son obligatorios.

Si no se define --superuser, se creará un usuario normal.Si no se define --password, se generará una contraseña aleatoria

    Ex : 
        /var/www/vhosts/PROJECT/python27/bin/python /usr/local/sbin/manage_dja_superusertest.py --username USERNAME --email TEST@domain.tld --project_dir /var/www/vhosts/PROJECT/PROJECT/ --settings PROJECT.settings.env 
Thibault Richard
fuente
0

Esto es lo que improvisé para Heroku post_deploy y una variable app.json predefinida :

if [[ -n "$CREATE_SUPER_USER" ]]; then
    echo "==> Creating super user"
    cd /app/example_project/src
    printf "from django.contrib.auth.models import User\nif not User.objects.exists(): User.objects.create_superuser(*'$CREATE_SUPER_USER'.split(':'))" | python /app/example_project/manage.py shell
fi

Con esto puedes tener una sola variable env:

CREATE_SUPER_USER=admin:admin@example.com:password

Me gusta la opción shell --command , pero no estoy seguro de cómo se obtiene el carácter de nueva línea en el script de comando. Sin el salto de línea, la ifexpresión da como resultado un error de sintaxis.

Janusz Skonieczny
fuente
0

Vaya al símbolo del sistema y escriba:

C:\WINDOWS\system32>pip install django-createsuperuser
Collecting django-createsuperuser
  Downloading https://files.pythonhosted.org/packages/93/8c/344c6367afa62b709adebee039d09229675f1ee34d424180fcee9ed857a5/django-createsuperuser-2019.4.13.tar.gz
Requirement already satisfied: Django>1.0 in c:\programdata\anaconda3\lib\site-packages (from django-createsuperuser) (2.2.1)
Requirement already satisfied: setuptools in c:\programdata\anaconda3\lib\site-packages (from django-createsuperuser) (41.0.1)
Requirement already satisfied: sqlparse in c:\programdata\anaconda3\lib\site-packages (from Django>1.0->django-createsuperuser) (0.3.0)
Requirement already satisfied: pytz in c:\programdata\anaconda3\lib\site-packages (from Django>1.0->django-createsuperuser) (2018.7)
Building wheels for collected packages: django-createsuperuser
  Running setup.py bdist_wheel for django-createsuperuser ... done
  Stored in directory: C:\Users\Arif Khan\AppData\Local\pip\Cache\wheels\0c\96\2a\e73e95bd420e844d3da1c9d3e496c92642a4f2181535440db2
Successfully built django-createsuperuser
Installing collected packages: django-createsuperuser

si no se ejecutó la migración, vaya a la carpeta de la aplicación django y ejecute lo siguiente

  1. python manage.py migrar
  2. python manage.py crea superusuario

luego bingo.

Arif Khan
fuente
0
python manage.py shell -c "from django.contrib.auth.models import User; \
                           User.objects.filter(username='admin1').exists() or \
                           User.objects.create_superuser('admin1',
                           '[email protected]', 'admin1')"
Raja R
fuente
0

Con shell_plus es mucho más fácil en realidad

echo "User.objects.create_superuser('[email protected]', 'test')" | python manage.py shell_plus

Como otros mencionaron, con Django 3.0 puede pasar las credenciales a través de variables de entorno. Sin embargo, este enfoque es mucho más flexible ya que le permite realizar cualquier otra tarea más complicada como eliminar todos los usuarios de pruebas, etc.

Pithikos
fuente