Erstellen Sie automatisch einen Administrator, wenn Sie die ./manage.py-Syncdb von Django ausführen

82

Mein Projekt befindet sich in der frühen Entwicklung. Ich lösche häufig die Datenbank und führe manage.py syncdbsie aus, um meine App von Grund auf neu einzurichten.

Leider erscheint dies immer:

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): 

Dann haben Sie einen Benutzernamen, eine gültige E-Mail-Adresse und ein Passwort angegeben. Das ist langweilig. Ich habe es satt zu tippen test\[email protected]\ntest\ntest\n.

Wie kann ich diesen Schritt automatisch überspringen und beim Ausführen programmgesteuert einen Benutzer erstellen manage.py syncdb?

ein bezahlter Nerd
quelle
syncdbwurde zugunsten von Datenmigrationen veraltet
Sdra

Antworten:

80

Ich weiß, dass die Frage bereits beantwortet wurde, aber ...

Ein viel einfacherer Ansatz besteht darin, die Daten des Authentifizierungsmoduls in eine JSON-Datei zu kopieren, sobald der Superuser erstellt wurde:

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

Sie können die Sitzungsdaten auch sichern:

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

Sie können dann die Sitzungsinformationen an den Speicherauszug des Authentifizierungsmoduls anhängen (und wahrscheinlich das expire_date erhöhen, damit es nicht abläuft ... niemals ;-).

Ab dann können Sie verwenden

/manage.py syncdb --noinput

Laden des Superusers und seiner Sitzung beim Erstellen der Datenbank ohne interaktive Eingabeaufforderung, in der Sie nach einem Superuser gefragt werden.

philgo20
quelle
1
Dies sollte wirklich die akzeptierte Antwort sein. Am einfachsten IMO. Link ist unterbrochen. :(
bnjmn
4
Wo soll ich das hinstellen, initial_data.jsondamit es es syncdbfindet? In den Dokumenten heißt es: "Im Fixtures-Verzeichnis jeder installierten Anwendung" . Ist das zB ./eggs/Django-1.6.5-py2.7.egg/django/contrib/auth/fixtures?
user272735
2
Dies ist seit Django 1.7 veraltet: docs.djangoproject.com/de/1.7/howto/initial-data/… Jetzt können Sie Datenmigrationen verwenden.
Germain Chazot
49

Anstatt Ihre gesamte Datenbank zu löschen, löschen Sie einfach die Tabellen Ihrer App, bevor Sie die Syncdb ausführen

Dies wird für Sie in einer einzigen Zeile (pro App) erledigt:

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

Der erste Befehl überprüft Ihre App und generiert das erforderliche SQL zum Löschen der Tabellen. Diese Ausgabe wird dann an die Datenbank weitergeleitet, um sie auszuführen.

Führen Sie anschließend Ihre Syncdb aus, um die Tabellen neu zu erstellen:

python manage.py syncdb
Andre Miller
quelle
2
Ich mag diese Antwort. Danke für den Vorschlag!
Seil
ich auch, danke! saubere Lösung, die es bereits verwendet, um einen sauberen Speicherauszug zu haben, den ich bei Bedarf synchronisiere.
Andrei-Niculae Petre
28

Der Schlüssel ist, --noinputzum Zeitpunkt der Synchronisierung zu verwenden und dann diesen one linerzu verwenden, um einen Superuser zu erstellen

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

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

Benutzer
quelle
5
Vielen Dank! Dies ist klarer als die anderen, robuster und erweiterbarer und eignet sich hervorragend für die erstmalige Ausführung Ihres Codes sowie für Testskripte und bestimmte Bereitstellungsszenarien und natürlich für das Entwicklungsszenario, das zu dieser Frage geführt hat.
Nealmcb
16

Wenn Sie - wie ich - die Möglichkeit haben möchten, wirklich mit einer neuen Datenbank zu beginnen, ohne diese Superuser-Frage gestellt zu bekommen, können Sie den Signal-Handler, der diese Frage stellt, einfach abmelden. Schauen Sie sich das Ende der Datei an:

django/contrib/auth/management/__init__.py

um zu sehen, wie die Registrierung der Superuser-Funktion durchgeführt wird. Ich habe festgestellt, dass ich diese Registrierung rückgängig machen kann und die Frage während "syncdb" nie gestellt wird, wenn ich diesen Code in meine "models.py" eingefügt habe:

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")

Ich bin nicht sicher, wie ich garantieren kann, dass dieser Code nach dem Django-Code ausgeführt wird, der die Registrierung vornimmt. Ich hatte gedacht, dass es davon abhängen würde, ob Ihre App oder die App django.contrib.auth zuerst in INSTALLED_APPS erwähnt wird, aber es scheint für mich zu funktionieren, unabhängig von der Reihenfolge, in der ich sie eingebe. Vielleicht werden sie alphabetisch erstellt und ich bin es Glück, dass der Name meiner App mit einem Buchstaben später als "d" beginnt? Oder ist Django gerade klug genug, um zuerst seine eigenen Sachen zu machen, dann meine, falls ich mit ihren Einstellungen Mist machen möchte? Lassen Sie mich wissen, wenn Sie es herausfinden. :-)

Brandon Rhodes
quelle
Schließlich implementiert diese und einen Haken hinzugefügt meine eigenen Testbenutzer zu erstellen (wenn settings.DEBUGist Trueautomatisch). Danke noch einmal!
Ein bezahlter Nerd
11

Ich habe diese Funktion überwinden mit Süd

Es ist ein Muss für jeden Django-Entwickler.

South ist ein Tool, mit dem Änderungen auf die Live-Site migriert werden können, ohne dass Informationen oder die Datenbankstruktur zerstört werden. Die resultierenden Änderungen können von Süden verfolgt und unter Verwendung der generierten Python-Dateien verwendet werden. Sie können dieselben Aktionen für eine alternative Datenbank ausführen.

Während der Entwicklung verwende ich dieses Tool, um meine Datenbankänderungen zu verfolgen - und um Änderungen an der Datenbank vorzunehmen, ohne sie zuerst zerstören zu müssen.

  1. easy_install south
  2. Fügen Sie Ihren installierten Apps 'Süd' hinzu

Vorschlagen des ersten Laufs von Süden auf einer App.

$ python manage.py schemamigration appname --init

Dadurch wird die Schemaerkennung in dieser App gestartet.

$ python manage.py migrate appname

Dadurch werden die Modelländerungen angewendet

  • Die Datenbank wird die neuen Modelle haben.

Modell nach dem ersten Lauf ändern

$ python manage.py schemamigration appname --auto

$ python manage.py migrate appname


Modelle haben sich geändert - Daten werden nicht zerstört. Plus Süden macht viel mehr ...

Glyzerin
quelle
9

Hinweis: Da der syncdbBefehl Version 1.7 veraltet ist . Verwenden Sie migrate stattdessen .

Auch Django 1.7 führte AppConfig ein , um den Initialisierungsprozess von Anwendungen anzupassen.

Seit Django 1.7 ist es daher am einfachsten, das zu erreichen, was Sie wollen AppConfig Unterklasse .

Angenommen, Sie haben zufällig einen eigenen example_app, der zu Ihrem hinzugefügt wird, INSTALLED_APPSund Sie möchten einen Administrator mit einem Administratorkennwort erstellen, wenn Sie ./manage.py migratevon Grund auf neu ausgeführt werden. Ich nehme auch an, dass die automatische Admin - Benutzererstellung nur in erforderlich ist dev Umgebung - nicht in Produktion .

Fügen Sie den folgenden Code hinzu 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, '[email protected]', PASSWORD)


class ExampleAppConfig(AppConfig):
    name = __package__

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

Fügen Sie außerdem den folgenden Verweis auf die App-Konfiguration in Apps hinzu example_app/__init__.py:

# example_app/__init__.py

default_app_config = 'example_app.apps.ExampleAppConfig'

Wobei die default_app_config ein String-Python-Pfad zur AppConfigUnterklasse ist, wie hier erwähnt .

Archibald
quelle
2
Leider funktioniert dies ab Django 1.9 django.contrib.authnicht mehr , da es zur Konfigurationszeit nicht mehr verfügbar ist. Dies ist beabsichtigt und seit 1.8 veraltet, so dass es unwahrscheinlich ist, dass es jemals wieder kommt. Was sehr traurig ist ... Ich mochte diesen Hack.
Adrian Petrescu
Okay, ich habe herausgefunden, wie Sie Ihren Code für Django 1.9 reparieren können! Ich habe Ihre Antwort mit den Korrekturen bearbeitet. Vielen Dank für die Veröffentlichung :)
Adrian Petrescu
3

Sie können Django-Finalware verwenden , um dies für Sie zu tun. Fügen finalwareSie einfach Ihre hinzu INSTALLED_APPSund fügen Sie Folgendes in Ihre ein settings.py:

SITE_SUPERUSER_USERNAME = 'myadmin'
SITE_SUPERUSER_EMAIL = '[email protected]'
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'

Führen Sie dann einfach ./manage.py syncdb(Django <1.7) oder ./manage.py migrate(Django> = 1.7) aus, und es wird automatisch ein Superuser erstellt oder der vorhandene für Sie aktualisiert.

Sie werden nie mehr aufgefordert, einen Superuser zu erstellen.

un33k
quelle
Wenn es von Ihnen erstellt wurde, fügen Sie bitte einen Haftungsausschluss hinzu
Erion S
Ist es kompatibel mit Django> = 2.0?
Dunatotatos
@ Dunatotatos ja das ist es. Unterstützung für Django-Versionen finden Sie auch in der Datei .travis.yml des
Repos
3

Seit Django 1.7 wird empfohlen, die Datenbank durch Datenmigrationen zu füllen. Um eine Datenmigration zum Erstellen des Administrators zu erstellen, müssen Sie zunächst eine leere Migration erstellen:

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

Dadurch wird eine leere Migration in erstellt myapp/migrations/000x__create-superuser.py. Bearbeiten Sie die Datei so, dass sie folgendermaßen aussieht:

# -*- 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='[email protected]')


class Migration(migrations.Migration):

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

    operations = [migrations.RunPython(create_superuser)]
Sdra
quelle
3

Ich habe beschlossen, ein Python-Skript wie dieses zu erstellen, um alle meine Inhalte zurückzusetzen [aktualisierte Version] [1.8 auch]:

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="[email protected]")
    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()

es wirkt wie ein Zauber!

PS: Stellen Sie sicher, dass Sie Ihren (Test-) Server dort stoppen, wo oben die Datenbank zuständig ist, bevor Sie dieses Skript ausführen!

Filippo.IOVINE
quelle
2

Schauen Sie sich den dumpdataVerwaltungsbefehl an. Zum Beispiel:

python manage.py dumpdata > initial_data.json

Wenn diese Datei, die als Fixture bezeichnet wird, den Namen initial_data(.xml oder .json) hat, wird diesyncdb Befehl sie auf und Ihre Tabellen entsprechend. Sie werden weiterhin gefragt, ob Sie einen Benutzer erstellen möchten, aber ich glaube, Sie können sicher mit "Nein" antworten. Danach wird die Datenbank basierend auf Ihrem Gerät gefüllt.

Weitere Informationen hierzu finden Sie in den Dokumenten .

Ryan Duffield
quelle
1
Sie können die Option --noinput an syncdb anhängen, um die interaktive Eingabeaufforderung zu verknüpfen, wenn Ihre initial_data.json
philgo20
2

Entwickeln mit SQLite. Löschen Sie die Datenbank, indem Sie die Datei löschen. Lade admin von Fixtures.

change manage.py (django 1.4):

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

Meine Lösung bestand darin, diese Authentifizierungstabellen beim Löschen meiner Datenbank einfach nicht zu löschen.

Priester
quelle
1

Wenn Sie es vorziehen, den Initialisierungscode direkt in die Python-Quelldatei einzugeben, kann dieser Code geändert werden, indem Sie "manage.py" ändern (und danke für den kleinen Code von 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 = '[email protected]'
            admin_password = 'superuser_password'
            additional_users = [
                                ['tempuser', '[email protected]', '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

Ich zeige hier nur den Code zur Benutzererstellung, aber Sie können diesen Code nach Belieben weiter verbessern.

Kenial
quelle
0

Ich verwende SQLite als Entwicklungsdatenbank. Nachdem Sie die Modellklassen geändert haben, löschen Sie einfach die entsprechenden Tabellen mit sqlite manager (einem Firefox-Plugin, das geöffnet ist, um die Daten zu überprüfen) und führen Sie sie aus manage.py syncdb, um die fehlenden Daten neu zu erstellen.

yanchenko
quelle