Automatycznie stwórz administratora podczas uruchamiania ./manage.py syncdb Django

82

Mój projekt jest na wczesnym etapie rozwoju. Często usuwam bazę danych i uruchamiam manage.py syncdbkonfigurację aplikacji od podstaw.

Niestety, to zawsze się pojawia:

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

Następnie musisz podać nazwę użytkownika, prawidłowy adres e-mail i hasło. To jest nudne. Mam dość pisania test\[email protected]\ntest\ntest\n.

Jak mogę automatycznie pominąć ten krok i programowo utworzyć użytkownika podczas pracy manage.py syncdb?

płatny frajer
źródło
syncdbzostał wycofany na korzyść migracji danych
Sdra

Odpowiedzi:

80

Wiem, że na to pytanie już udzielono odpowiedzi, ale ...

Dużo prostszym podejściem jest zrzucenie danych modułu autoryzacji do pliku json po utworzeniu superużytkownika:

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

Możesz również zrzucić dane sesji:

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

Następnie możesz dołączyć informacje o sesji do zrzutu modułu autoryzacji (i prawdopodobnie zwiększyć datę ważności, aby nie wygasała ... nigdy ;-).

Od tego momentu możesz używać

/manage.py syncdb --noinput

aby załadować superużytkownika i jego sesję podczas tworzenia bazy danych bez interaktywnego pytania o superużytkownika.

philgo20
źródło
1
To naprawdę powinna być akceptowana odpowiedź. Najprostsza IMO. Link jest uszkodzony. :(
bnjmn
4
Gdzie mam umieścić, initial_data.jsonżeby to syncdbznalazło? Dokumentacja mówi: „W katalogu fixtures każdej zainstalowanej aplikacji” . Czy to np. ./eggs/Django-1.6.5-py2.7.egg/django/contrib/auth/fixtures?
user272735
2
Jest to przestarzałe od wersji Django 1.7: docs.djangoproject.com/en/1.7/howto/initial-data/ ... Teraz możesz używać migracji danych.
Germain Chazot,
49

Zamiast usuwać całą bazę danych, po prostu usuń tabele swojej aplikacji przed uruchomieniem syncdb

To zrobi to za Ciebie w jednej linii (na aplikację):

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

Pierwsze polecenie sprawdzi Twoją aplikację i wygeneruje wymagany kod SQL do usunięcia tabel. To wyjście jest następnie przesyłane potokiem do powłoki dbshell w celu jej wykonania.

Po zakończeniu uruchom syncdb, aby odtworzyć tabele:

python manage.py syncdb
Andre Miller
źródło
2
Podoba mi się ta odpowiedź. Dzieki za sugestie!
ropable
ja też, dzięki! czyste rozwiązanie, już używam go, aby mieć czysty zrzut, który synchronizuję, kiedy tylko potrzebuję.
Andrei-Niculae Petre
28

Kluczem jest użycie --noinputw momencie syncdb, a następnie użycie tego one linerdo utworzenia superużytkownika

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

Źródło: http://source.mihelac.org/2009/10/23/django-avoiding-typing-password-for-superuser/

użytkownik
źródło
5
Dzięki! Jest to jaśniejsze niż inne, bardziej niezawodne i rozszerzalne oraz świetne do użycia przy pierwszym uruchomieniu kodu, a także w skryptach testowych i niektórych scenariuszach wdrożeniowych oraz oczywiście w scenariuszu programistycznym, który doprowadził do tego pytania.
nealmcb
16

Jeśli chcesz mieć możliwość - tak jak ja - naprawdę rozpocząć od nowej bazy danych bez pytania o superużytkownika, możesz po prostu wyrejestrować program obsługi sygnału, który zadaje to pytanie. Sprawdź sam dół pliku:

django/contrib/auth/management/__init__.py

aby zobaczyć, jak wykonywana jest rejestracja funkcji superużytkownika. Okazało się, że mogę cofnąć tę rejestrację i nigdy nie zostałem zadany pytanie podczas „syncdb”, gdybym umieścił ten kod w moim „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")

Nie jestem pewien, jak zagwarantować, że ten kod zostanie uruchomiony po kodzie Django, który dokonuje rejestracji. Myślałem, że będzie to zależeć od tego, czy twoja aplikacja lub aplikacja django.contrib.auth zostanie wymieniona jako pierwsza w INSTALLED_APPS, ale wydaje mi się, że działa to niezależnie od kolejności, w jakiej je umieściłem. Może są zrobione alfabetycznie i jestem szczęście, że nazwa mojej aplikacji zaczyna się na literę późniejszą niż „d”? A może Django jest wystarczająco sprytny, aby najpierw robić swoje własne rzeczy, a potem moje, na wypadek, gdybym chciał się bawić z ich ustawieniami? Daj mi znać, jeśli się dowiesz. :-)

Brandon Rhodes
źródło
Wreszcie zaimplementowałem to i dodałem hak do automatycznego tworzenia własnego użytkownika testowego (jeśli settings.DEBUGjest True). Dzięki jeszcze raz!
płatny kujon
11

Pokonałem tę funkcję, używając południa

To pozycja obowiązkowa dla każdego programisty django.

South to narzędzie zaprojektowane w celu ułatwienia migracji zmian do działającej witryny bez niszczenia informacji lub struktury bazy danych. Wynikowe zmiany mogą być śledzone przez południe i za pomocą wygenerowanych plików Pythona - mogą wykonywać te same czynności na alternatywnej bazie danych.

Podczas programowania używam tego narzędzia do śledzenia zmian w mojej bazie danych - i do wprowadzania zmian w bazie danych bez konieczności jej wcześniejszego niszczenia.

  1. easy_install południe
  2. Dodaj „południe” do zainstalowanych aplikacji

Proponowanie pierwszej jazdy na południe w aplikacji.

$ python manage.py schemamigration appname --init

Spowoduje to zainicjowanie wykrywania schematu w tej aplikacji.

$ python manage.py migrate appname

Spowoduje to zastosowanie zmian modelu

  • Baza danych będzie zawierała nowe modele.

Zmiana modelu po pierwszym uruchomieniu

$ python manage.py schemamigration appname --auto

$ python manage.py migrate appname


Modele ulegną zmianie - dane nie zostaną zniszczone. Poza tym południe robi znacznie więcej ...

Gliceryna
źródło
9

Uwaga: od wersji 1.7 syncdbpolecenie jest przestarzałe . Użyj migrate zamiast tego .

Również Django 1.7 wprowadziło AppConfig jako sposób na dostosowanie procesu inicjalizacji aplikacji.

Tak więc od Django 1.7 najprostszym sposobem osiągnięcia tego, co chcesz, jest zastosowanie AppConfigpodklasy klasy.

Powiedzmy, zdarzy ci się mieć swój własny example_app, który jest dodany do INSTALLED_APPSi chcesz stworzyć i administratora użytkownikowi administratora hasło przy każdym uruchomieniu ./manage.py migrateod zera. Zakładam też, że automatyczne tworzenie administratora jest wymagane tylko w środowisku deweloperskim, a nie produkcyjnym .

Dodaj następujący kod do 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)

Dodaj również następujące odniesienie do konfiguracji aplikacji w aplikacjach example_app/__init__.py:

# example_app/__init__.py

default_app_config = 'example_app.apps.ExampleAppConfig'

Gdzie default_app_config to ścieżka w języku Python do AppConfigpodklasy, jak wspomniano tutaj .

Archibald
źródło
2
Niestety, to już nie działa od wersji Django 1.9, ponieważ django.contrib.authnie jest już dostępne w czasie konfiguracji. Jest to zgodne z projektem i zostało wycofane od 1.8, więc jest mało prawdopodobne, aby kiedykolwiek wrócił. Co jest bardzo smutne ... Podobał mi się ten hack.
Adrian Petrescu
Okay, wymyśliłem, jak naprawić kod, aby działał z Django 1.9! Zmieniłem twoją odpowiedź z poprawkami. Dzięki za wysłanie :)
Adrian Petrescu
5

manage.py resetPolecenie zresetowania bazy danych bez niszcząc utworzony superużytkownika. Dane muszą jednak zostać ponownie zaimportowane.

tjb
źródło
1
reset został zastąpiony przez flush z Django 1.5 stackoverflow.com/questions/15454008/…
tjb
3

Możesz użyć django-finalware, aby zrobić to za Ciebie. Po prostu dodaj finalwaredo swojego INSTALLED_APPSi umieść w swoim 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'

Następnie po prostu uruchom ./manage.py syncdb(Django <1.7) lub ./manage.py migrate(Django> = 1.7), a to automatycznie utworzy superużytkownika lub zaktualizuje istniejącego.

Nigdy więcej nie pojawia się monit o utworzenie superużytkownika.

un33k
źródło
Jeśli został utworzony przez Ciebie, dodaj wyłączenie odpowiedzialności
Erion S
Czy jest kompatybilny z Django> = 2.0?
Dunatotatos
@Dunatotatos tak jest. Obsługę wersji Django można również znaleźć w pliku .travis.yml repozytorium
un33k
3

Od wersji Django 1.7 sugerowanym sposobem zapełniania bazy danych są migracje danych. Aby utworzyć migrację danych w celu utworzenia administratora, należy najpierw utworzyć pustą migrację:

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

Spowoduje to utworzenie pustej migracji w myapp/migrations/000x__create-superuser.py. Edytuj plik, aby wyglądał następująco:

# -*- 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
źródło
3

Postanowiłem stworzyć skrypt w Pythonie, taki jak ten, aby zresetować wszystkie moje rzeczy [zaktualizowana wersja] [również 1.8]:

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

To działa jak urok!

PS: Pamiętaj, aby zatrzymać (testowy) serwer, na którym znajduje się powyżej db, przed uruchomieniem tego skryptu!

Filippo.IOVINE
źródło
2

Spójrz na dumpdatapolecenie zarządzania. Na przykład:

python manage.py dumpdata > initial_data.json

Jeśli ten plik, zwany urządzeniem, ma nazwę initial_data(.xml lub .json), to syncdbpolecenie pobierze go i odpowiednio zapełni tabele. Nadal zapyta Cię, czy chcesz utworzyć użytkownika, ale wierzę, że możesz spokojnie odpowiedzieć „nie”, po czym zapełni bazę danych w oparciu o Twoje urządzenie.

Więcej informacji na ten temat można znaleźć w dokumentacji .

Ryan Duffield
źródło
1
Możesz dołączyć opcję --noinput do syncdb, aby skrócić interaktywny monit, jeśli masz informacje o superużytkowniku i sesji w
pliku
2

Rozwój z sqlite. Wyczyść bazę danych, usuwając plik. Załaduj administratora z urządzeń.

zmień 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
źródło
2
if 'syncdb' in sys.argv: sys.argv.append('--noinput')
TimP
1

Moim rozwiązaniem było po prostu nie usuwać tych tabel uwierzytelniania podczas czyszczenia mojej bazy danych.

ksiądzc
źródło
1

Jeśli wolisz wpisać kod inicjujący bezpośrednio w pliku źródłowym Pythona, ten zmodyfikowany kod manage.py może pomóc (i dzięki za mały kod 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

Pokazuję tutaj tylko kod tworzenia użytkownika, ale możesz ulepszyć ten kod bardziej, jak chcesz.

Kenial
źródło
0

Używam sqlite jako bazy danych deweloperów. Po zmianie klas modelu po prostu upuść odpowiednie tabele za pomocą sqlite Manager (wtyczka do firefox, otwórz, aby sprawdzić dane i tak) i uruchom manage.py syncdbponownie, aby odtworzyć brakujące.

yanchenko
źródło