Cree automáticamente un usuario administrador cuando ejecute ./manage.py syncdb de Django


82

Mi proyecto está en desarrollo temprano. Con frecuencia elimino la base de datos y ejecuto manage.py syncdbpara configurar mi aplicación desde cero.

Desafortunadamente, esto siempre aparece:

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): 

Luego, debe proporcionar un nombre de usuario, una dirección de correo electrónico válida y una contraseña. Esto es tedioso. Me estoy cansando de escribir test\nx@x.com\ntest\ntest\n.

¿Cómo puedo omitir este paso automáticamente y crear un usuario mediante programación cuando se ejecuta manage.py syncdb?


syncdbha quedado en desuso a favor de las migraciones de datos
Sdra

Respuestas:


80

Sé que la pregunta ya ha sido respondida pero ...

Un enfoque mucho más simple es volcar los datos del módulo de autenticación en un archivo json una vez que se ha creado el superusuario:

 ./manage.py dumpdata --indent=2 auth > initial_data.json

También puede volcar los datos de las sesiones:

./manage.py dumpdata --indent=2 sessions

Luego puede agregar la información de la sesión al volcado del módulo de autenticación (y probablemente aumentar el expire_date para que no expire ... nunca ;-).

A partir de entonces, puedes usar

/manage.py syncdb --noinput

para cargar el superusuario y su sesión al crear la base de datos sin un mensaje interactivo que le pregunte sobre un superusuario.


1
Esta debería ser realmente la respuesta aceptada. La OMI más sencilla. El enlace está roto. :(
bnjmn

4
¿Dónde debo poner initial_data.jsonpara que lo syncdbencuentre? Los documentos dicen: "En el directorio de accesorios de cada aplicación instalada" . ¿Eso es por ejemplo ./eggs/Django-1.6.5-py2.7.egg/django/contrib/auth/fixtures?
user272735

2
Esto está en desuso desde Django 1.7: docs.djangoproject.com/en/1.7/howto/initial-data/… Ahora puede usar las migraciones de datos.
Germain Chazot

49

En lugar de eliminar toda su base de datos, simplemente elimine las tablas de su aplicación antes de ejecutar syncdb

Esto lo logrará por usted en una sola línea (por aplicación):

python manage.py sqlclear appname | python manage.py dbshell

El primer comando examinará su aplicación y generará el SQL necesario para eliminar las tablas. Luego, esta salida se envía al dbshell para ejecutarla.

Una vez hecho esto, ejecute su syncdb para recrear las tablas:

python manage.py syncdb

2
Me gusta esta respuesta. ¡Gracias por la sugerencia!
ropable

¡yo también gracias! solución limpia, ya la estoy usando para tener un volcado limpio que sincronizo siempre que lo necesito.
Andrei-Niculae Petre

28

La clave es usar --noinputen el momento de syncdb y luego usar esto one linerpara crear superusuario

echo "from django.contrib.auth.models import User; User.objects.create_superuser('myadmin', 'myemail@example.com', 'hunter2')" | python manage.py shell

Crédito: http://source.mihelac.org/2009/10/23/django-avoiding-typing-password-for-superuser/


5
¡Gracias! Esto es más claro que los demás, más robusto y extensible, y excelente para usar la primera vez que ejecuta su código, así como en scripts de prueba y ciertos escenarios de implementación y, por supuesto, para el escenario de desarrollo que llevó a la pregunta.
nealmcb

16

Si desea la capacidad, como yo, de comenzar realmente con una base de datos nueva sin que se le haga esa pregunta de superusuario, entonces puede simplemente cancelar el registro del controlador de señal que hace esa pregunta. Mira la parte inferior del archivo:

django/contrib/auth/management/__init__.py

para ver cómo se realiza el registro de la función de superusuario. Descubrí que podía revertir este registro y que nunca me hicieran la pregunta durante "syncdb", si colocaba este código en mi "models.py":

from django.db.models import signals
from django.contrib.auth.management import create_superuser
from django.contrib.auth import models as auth_app

# Prevent interactive question about wanting a superuser created.  (This
# code has to go in this otherwise empty "models" module so that it gets
# processed by the "syncdb" command during database creation.)

signals.post_syncdb.disconnect(
    create_superuser,
    sender=auth_app,
    dispatch_uid = "django.contrib.auth.management.create_superuser")

No estoy seguro de cómo garantizar que este código se ejecute después del código de Django que realiza el registro. Pensé que dependería de si su aplicación o la aplicación django.contrib.auth se menciona primero en INSTALLED_APPS, pero parece funcionar para mí independientemente del orden en que las coloque. Tal vez estén hechas alfabéticamente y estoy ¿Tiene suerte de que el nombre de mi aplicación comience con una letra posterior a la "d"? ¿O es Django lo suficientemente inteligente como para hacer sus propias cosas primero, luego las mías en caso de que quiera alterar su configuración? Avísame si lo descubres. :-)


Finalmente implementé esto y agregué un gancho para crear mi propio usuario de prueba (si settings.DEBUGes True) automáticamente. ¡Gracias de nuevo!
un nerd pagado

11

Superé esta característica usando el sur

Es imprescindible para cualquier desarrollador de django.

South es una herramienta diseñada para ayudar a migrar los cambios al sitio en vivo sin destruir la información o la estructura de la base de datos. Los cambios resultantes pueden ser rastreados por South y usando los archivos de Python generados, pueden realizar las mismas acciones en una base de datos alternativa.

Durante el desarrollo, utilizo esta herramienta para realizar un seguimiento de los cambios de mi base de datos y para realizar un cambio en la base de datos sin la necesidad de destruirla primero.

  1. easy_install sur
  2. Agregue 'sur' a sus aplicaciones instaladas

Proponer la primera carrera del sur en una aplicación.

$ python manage.py schemamigration appname --init

Esto iniciará la detección de esquemas en esa aplicación.

$ python manage.py migrate appname

Esto aplicará los cambios del modelo.

  • La base de datos tendrá los nuevos modelos.

Cambiar un modelo después de la primera ejecución

$ python manage.py schemamigration appname --auto

$ python manage.py migrate appname


Los modelos habrán cambiado, los datos no se destruyen. Además, el sur hace mucho más ...


9

Nota: dado que el syncdbcomando de la versión 1.7 está obsoleto . Úselo en su migrate lugar .

También Django 1.7 introdujo AppConfig como un medio para personalizar el proceso de inicialización de las aplicaciones.

Por lo tanto, desde Django 1.7, la forma más sencilla de lograr lo que desea es emplear una AppConfigsubclase.

Digamos, le sucede que tiene su propia example_appque se añade a tu INSTALLED_APPSy que desea crear y administrador de usuario con administrador de contraseña cada vez que se ejecuta ./manage.py migratea partir de cero. También supongo que es necesaria la creación de usuario de administración automática sólo en dev medio ambiente - no en la producción .

Agregue el siguiente código a example_app/apps.py

# example_app/apps.py

from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate
from django.contrib.auth.apps import AuthConfig


USERNAME = "admin"
PASSWORD = "admin"


def create_test_user(sender, **kwargs):
    if not settings.DEBUG:
        return
    if not isinstance(sender, AuthConfig):
        return
    from django.contrib.auth.models import User
    manager = User.objects
    try:
        manager.get(username=USERNAME)
    except User.DoesNotExist:
        manager.create_superuser(USERNAME, 'x@x.com', PASSWORD)


class ExampleAppConfig(AppConfig):
    name = __package__

    def ready(self):
        post_migrate.connect(create_test_user)

También agregue la siguiente referencia a la configuración de la aplicación dentro de las aplicaciones example_app/__init__.py:

# example_app/__init__.py

default_app_config = 'example_app.apps.ExampleAppConfig'

Donde default_app_config es una ruta de Python de cadena a la AppConfigsubclase como se menciona aquí .


2
Desafortunadamente, esto ya no funciona a partir de Django 1.9, porque django.contrib.authya no está disponible en el momento de la configuración. Esto es por diseño y ha sido obsoleto desde 1.8, por lo que es poco probable que vuelva a aparecer. Lo cual es muy triste ... Me gustó este truco.
Adrian Petrescu

¡De acuerdo, descubrí cómo arreglar tu código para que funcione con Django 1.9! He editado tu respuesta con las correcciones. Gracias por publicarlo :)
Adrian Petrescu


3

Puede usar django-finalware para hacer esto por usted. Simplemente agregue finalwarea su INSTALLED_APPSe incluya lo siguiente en su settings.py:

SITE_SUPERUSER_USERNAME = 'myadmin'
SITE_SUPERUSER_EMAIL = 'myadmin@example.com'
SITE_SUPERUSER_PASSWORD  = 'mypass'  # this can be set from a secret file.

# optional object id. Ensures that the superuser id is not set to `1`.
# you can use this as a simple security feature
SITE_SUPERUSER_ID = '343'

Luego, simplemente ejecute ./manage.py syncdb(Django <1.7) o ./manage.py migrate(Django> = 1.7), y automáticamente creará un superusuario o actualizará el existente por usted.

Ya no se le pedirá que cree un superusuario.


Si fue creado por usted, agregue un descargo de responsabilidad
Erion S

¿Es compatible con Django> = 2.0?
Dunatotatos

@Dunatotatos sí lo es. El soporte de la versión de Django también se puede encontrar en el archivo .travis.yml del repositorio
un33k

3

Desde Django 1.7, la forma sugerida de poblar la base de datos es mediante migraciones de datos. Para crear una migración de datos para crear el administrador, primero debe crear una migración vacía:

./manage.py makemigrations --empty myapp --name create-superuser

Esto creará una migración vacía en myapp/migrations/000x__create-superuser.py. Edite el archivo para que se vea así:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.contrib.auth.models import User


def create_superuser(apps, schema_editor):
    User.objects.create_superuser(username='myadmin', password='mypassword', email='myemail@gmail.com')


class Migration(migrations.Migration):

    dependencies = [('myapp', '000y_my-previous-migration-file'),]

    operations = [migrations.RunPython(create_superuser)]

3

He resuelto la creación de un script de Python como este para restablecer todas mis cosas [versión actualizada] [1.8 también]:

import os
import sys

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "main.settings.dev")

from django.conf import settings
from django.core import management
from django import get_version

PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
if PROJECT_ROOT not in sys.path:
    sys.path.append(PROJECT_ROOT)

yn = raw_input('Are you sure you want to reset everything? (y/n) ')
if yn == 'y':

    # Drops the db / creates the db
    if settings.DATABASES['default']['ENGINE'].find('mysql') != -1:
        os.system('mysqladmin -uroot -pIronlord0 -f drop db')
        os.system('mysqladmin -uroot -pIronlord0 -f create db')
    elif settings.DATABASES['default']['ENGINE'].find('psycopg2') != -1:
        os.system('psql -U postgres -c "DROP DATABASE db"')
        os.system('psql -U postgres -c "CREATE DATABASE db WITH OWNER = admin"')
    elif settings.DATABASES['default']['ENGINE'].find('sqlite3') != -1:
        try:
            os.remove(os.path.join(PROJECT_ROOT, 'data.db'))
        except:
            pass

    # Getting application handle here otherwise db gets allocated and it can not be destroyed.
    if get_version() > '1.6.10':
        from django.core.wsgi import get_wsgi_application
        application = get_wsgi_application()

    management.call_command('syncdb', interactive=False)

    # Creates admin/password
    from django.contrib.auth.management.commands import changepassword
    management.call_command('createsuperuser', interactive=False, username="admin", email="xxx@example.com")
    command = changepassword.Command()
    command._get_pass = lambda *args: 'password'
    if get_version() >= '1.8':
        command.execute(username="admin")
    else:
        command.execute("admin")


    # Creates the default site entry
    from django.contrib.sites.models import Site
    site = Site.objects.get_current()
    site.domain = 'www.example.com'
    site.name = ' xxx '
    site.save()

¡funciona a las mil maravillas!

PD: ¡Asegúrese de detener su servidor (de prueba) donde el db anterior está a cargo antes de ejecutar este script!


2

Eche un vistazo al dumpdatacomando de gestión. Por ejemplo:

python manage.py dumpdata > initial_data.json

Si este archivo, llamado accesorio, se llama initial_data(.xml o .json), el syncdbcomando lo recogerá y completará sus tablas en consecuencia. Todavía le preguntará si desea crear un usuario, pero creo que puede responder con seguridad "no", después de lo cual completará la base de datos en función de su dispositivo.

Puede encontrar más información sobre esto en los documentos .


1
Puede agregar la opción --noinput a syncdb para acceder al indicador interactivo si tiene información de superusuario y sesión en su initial_data.json
philgo20

2

Desarrollando con sqlite. Limpiar la base de datos eliminando el archivo. Cargar admin desde accesorios.

cambiar manage.py (django 1.4):

# hack to prevent admin promt
if  len(sys.argv) == 2 and sys.argv[1] == 'syncdb':
    sys.argv.append('--noinput')

2
if 'syncdb' in sys.argv: sys.argv.append('--noinput')
TimP

1

Mi solución a esto fue simplemente no eliminar esas tablas de autenticación al borrar mi base de datos.


1

Si prefiere escribir el código de inicialización directamente en el archivo fuente de Python, este código modificado manage.py podría ayudar (¡y gracias por el pequeño código de Cjkjvfnby!):

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    # set your django setting module here
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings") 

    from django.core.management import execute_from_command_line

    # hack to prevent admin prompt
    if len(sys.argv) == 2 and sys.argv[1] == 'syncdb':
        sys.argv.append('--noinput')

    execute_from_command_line(sys.argv)

    # additional process for creation additional user, misc data, and anything
    for arg in sys.argv:
        # if syncdb occurs and users don't exist, create them
        if arg.lower() == 'syncdb':
            print 'syncdb post process...'
            from django.contrib.auth.models import User

            admin_id = 'admin'
            admin_email = 'superuser@mail.com'
            admin_password = 'superuser_password'
            additional_users = [
                                ['tempuser', 'user_email@mail.com', 'tempuser_password']
                                ]

            # admin exists?
            user_list = User.objects.filter(username=admin_id)
            if len(user_list) == 0: 
                print 'create superuser: ' + admin_id
                new_admin = User.objects.create_superuser(admin_id, admin_email, admin_password)

            # additional user exists?
            for additional_user in additional_users:
                user_list = User.objects.filter(username=additional_user[0])
                if len(user_list) == 0: 
                    print 'create additional user: ' + additional_user[0]
                    new_admin = User.objects.create_user(additional_user[0], additional_user[1], additional_user[2])

            # any other data

Solo estoy mostrando el código de creación de usuario aquí, pero puede mejorar este código más si lo desea.


0

Estoy usando sqlite como base de datos de desarrollo. Después de cambiar las clases del modelo, simplemente suelte las tablas correspondientes con sqlite manager (un complemento de Firefox, ábralo para inspeccionar los datos de todos modos) y ejecútelo manage.py syncdbpara recrear lo que falta.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.