Jak zautomatyzować createuperuser na django?

129

Chcę auto biegu manage.py createsuperuserna djangoale szwy, że nie ma możliwości ustawienia domyślne hasło.

Jak mogę to uzyskać? Musi być niezależny od bazy danych django.

bogdan
źródło
1
czy zastanawiałeś się nad zapisaniem utworzonego superużytkownika jako urządzenia i załadowaniem go za pomocą manage.py?
turbotux
1
Odpowiedź @turbotux Hendrik F przyjmuje podobne podejście do tego, co sugerujesz, z dodatkową możliwością odczytu wartości (login, hasło ...) z zmiennych env (lub systemu plików, ...). Zdecydowanie sugerowałbym pójście w tym kierunku zamiast skryptów pythonowych ad-hoc, które mają problemy po ponownym uruchomieniu aplikacji.
Ad N

Odpowiedzi:

145

Jeśli odwołujesz się bezpośrednio do użytkownika , kod nie będzie działał w projektach, w których ustawienie AUTH_USER_MODEL zostało zmienione na inny model użytkownika. Bardziej ogólny sposób tworzenia użytkownika to:

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

ORYGINALNA ODPOWIEDŹ

Oto prosta wersja skryptu do tworzenia superużytkownika:

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | python manage.py shell
Tk421
źródło
2
bardzo przydatne, gdy próbujesz utworzyć superużytkownika w heroku, a twoja sieć blokuje port 5000
Vic,
4
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
Usunąłbym
12
Osobiście nie uważam, że usuwanie użytkownika w każdej kompilacji jest dobrym pomysłem. Ryzykujesz niezamierzone usunięcie wszelkich powiązanych rekordów za pomocą usuwania kaskadowego. Bezpieczniejszą opcją jest po prostu wykupienie pomocy, jeśli użytkownik już istnieje (lub zaktualizowanie istniejącego rekordu użytkownika).
Will
6
Przynajmniej w Django 1.11. kolejność argumentów to („nazwa użytkownika”, „e-mail”, „hasło”), a nie („adres e-mail”, „nazwa użytkownika”, „hasło”). Zobacz: docs.djangoproject.com/en/1.11/ref/contrib/auth/…
np8
3
from django.contrib.auth.models import Usernie działa. Użyj tego: from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'my secure password')
dcalde
49

Sam szukałem odpowiedzi na to pytanie. Postanowiłem stworzyć polecenie Django, które rozszerza createsuperuserpolecenie podstawowe ( 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()

Przykładowe zastosowanie:

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

Ma to tę zaletę, że nadal obsługuje domyślne użycie poleceń, a jednocześnie umożliwia nieinteraktywne użycie do określania hasła.

Adam Charnock
źródło
4
To powinna być najbardziej pozytywna (i zaakceptowana) odpowiedź.
bruno desthuilliers
Chciałbym, żeby domyślne createsuperusermiało to --passwordpole
shadi
1
Możesz dodać przykład użycia:./manage.py createsuperuser2 --username test1 --password 123321 --noinput --email '[email protected]'
shadi
2
jak jest createsuperuser2mapowane do tej klasy, funkcja
Srinath Ganesh
2
@SrinathGanesh spójrz na docs.djangoproject.com/en/1.8/howto/custom-management-commands Musisz nazwać plik Pythona createsuperuser2.pyi umieścić go w zdefiniowanej strukturze katalogów z linku powyżej.
ElectRocnic
43

Używam './manage.py shell -c':

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

Nie używa to dodatkowego echa, ma tę zaletę, że można go przekazać do kontenera dockera w celu wykonania. Bez potrzeby używania sh -c "...", co powoduje, że cytat ucieka z piekła.

I pamiętaj, że najpierw jest nazwa użytkownika, a nie e-mail.

Jeśli masz niestandardowy model użytkownika, musisz go zaimportować, a nie auth.models.User

tak
źródło
1
Pracował dla mnie. Dzięki!
TimH - Codidact
Wydaje się, że nie działa dla mnie, widzę:AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'
Brodan
kiedy masz niestandardowy model użytkownika, taki jak users.User musisz importować z niego, a nie zauth.User
yvess
30

Sugerowałbym uruchomienie migracji danych , więc kiedy migracje są stosowane do projektu, w ramach migracji tworzony jest superużytkownik. Nazwę użytkownika i hasło można ustawić jako zmienne środowiskowe. Jest to również przydatne podczas uruchamiania aplikacji w kontenerze (zobacz ten wątek jako przykład)

Twoja migracja danych wyglądałaby wtedy następująco:

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),
    ]

Mam nadzieję, że to pomoże!

EDYCJA : Niektórzy mogą zadać pytanie, jak ustawić te zmienne środowiskowe i uświadomić Django o ich istnieniu. Jest wiele sposobów i odpowiedź na to pytanie znajduje się w innych postach SO, ale jako szybki wskaźnik, .envdobrym pomysłem jest utworzenie pliku. Możesz wtedy użyć pakietu python-dotenv , ale jeśli skonfigurowałeś środowisko wirtualne z pipenv, automatycznie ustawi on zmienne envars w twoim .envpliku. Podobnie, uruchomienie aplikacji przez docker-compose może spowodować odczytanie .envpliku.

Hendrik F
źródło
1
WSKAZÓWKA: Rozważ to podejście . To jest odpowiedź wysokiej jakości: naturalnie wykorzystuje wbudowane funkcje Django, aby odpowiedzieć na pytanie, zamiast powtarzać skrypty Pythona ad-hoc, a ponadto naturalnie rozwiązuje największy problem z zaakceptowaną odpowiedzią (migracja jest stosowana tylko raz na wdrożeniu , więc użytkownik jest tworzony tylko raz). Świetnie sprawdza się w kontekście kontenera.
Ad N
To wydaje się świetna odpowiedź. Nadal nie wiem, gdzie w projekcie pasuje ten fragment kodu?
Pablo Ruiz Ruiz
Powinien znajdować się w folderze migracji, np. root/⁨mysite⁩/myapp⁩/⁨migrations⁩- jeśli czytasz dokumenty, wyjaśnia, jak możesz utworzyć pustą migrację i ją zmodyfikowaćpython manage.py makemigrations --empty yourappname
Hendrik F
Dlaczego potrzebujesz DJANGO_DB_NAME? nigdy nie jest używany.
thoroc
Należy wspomnieć o dodaniu następujących elementów, aby załadować zmienne .env do settings.pypliku:python # loading .env from dotenv import load_dotenv from pathlib import Path env_path = Path('.', '.env') load_dotenv(dotenv_path=env_path)
thoroc
23

Jak Django 3.0 można użyć domyślnego createsuperuser --noinputpolecenia i ustawić wszystkie wymagane pola (w tym hasła) jako zmienne środowiskowe DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAILna przykład. --noinputflaga jest wymagana.

Pochodzi z oryginalnej dokumentacji: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-createsuperuser

i właśnie sprawdziłem - działa. Teraz możesz łatwo wyeksportować te zmienne środowiskowe i dodać je createsuperuserdo swoich skryptów i potoków.

Alexey Trofimov
źródło
14

Możesz napisać prosty skrypt w Pythonie do automatyzacji tworzenia superużytkowników. UserModel jest po prostu normalnym modelu Django, więc chcesz śledzić normalny proces pisania samodzielnych Django skryptu. Dawny:

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

Możesz również przekazać createsuperuserkilka opcji, a mianowicie --noinputi --username, które pozwolą ci automatycznie tworzyć nowych superużytkowników, ale nie będą mogli się zalogować, dopóki nie ustawisz dla nich hasła.

zeekay
źródło
2
Ok cretesuperuser, ale jak wtedy ustawić hasło? Chciałbym to zrobić w skrypcie basha ...
caneta
10

Aktualnie najczęściej głosowana odpowiedź:

  • Usuwa użytkownika, jeśli istnieje i jak zauważył @Groady w komentarzach, ryzykujesz niezamierzone usunięcie wszelkich powiązanych rekordów za pomocą usuwania kaskadowego.
  • Sprawdza filtrowanie istnienia superużytkowników przez pocztę, więc jeśli dwóch superużytkowników ma tę samą pocztę, Bóg wie, który z nich usuwa.
  • Aktualizacja parametrów skryptu: nazwy użytkownika, hasła i poczty jest uciążliwa.
  • Nie rejestruje tego, co zrobił.

Ulepszona wersja to:

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
źródło
2
Znacznie czystsze (lepsze) niż zaakceptowana odpowiedź. Można też wykorzystali: if not User.objects.filter(username = username).exists(),
Philippe Fanaro
5
DJANGO_SUPERUSER_USERNAME=testuser \
DJANGO_SUPERUSER_PASSWORD=testpass \
python manage.py createsuperuser --noinput

Dokumentacja dla polecenia createuser

Rafal Enden
źródło
To najłatwiejsze rozwiązanie. Ale możesz nadpisać noinputflagę innymi parametrami:DJANGO_SUPERUSER_PASSWORD=testpass python manage.py createsuperuser --username testuser --email [email protected] --noinput
dannydedog
1

Użyłem jednej wkładki Tk421, ale otrzymałem komunikat o błędzie: 1) Myślę, że używam późniejszej wersji Django (1.10) Manager isn't available; 'auth.User' has been swapped for 'users.User' 2) kolejność parametrów do create_superuser była nieprawidłowa.

Więc zastąpiłem go:

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

i bardzo mi się podoba, że ​​działa również na wdrożeniu 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

To będzie dobrze działać wielokrotnie. Używam go na początku projektu, więc nie martw się o okropne kaskadowe usuwanie, które może nastąpić później.

Wróciłem po problemach z uruchomieniem tego wewnątrz local () z tkaniny. wydawało się, że dzieje się tak, że symbol fajki oznacza, że ​​był interpretowany lokalnie, a nie na heroku. Aby to posortować, zawinąłem polecenie w cudzysłów. Następnie musiał użyć potrójnych podwójnych cudzysłowów dla ciągów znaków Pythona w pojedynczych cudzysłowach całego polecenia Pythona.

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
źródło
1

Rozwiązanie oparte na Adam Charnock podejścia jest powyżej są dostępne w postaci pakietu Python teraz. To wymaga trzech kroków:

  1. Zainstalować: pip install django-createsuperuserwithpassword

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

  3. Zastosować:

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

Otóż ​​to.

Sebastian
źródło
0

Ten mały skrypt w Pythonie może stworzyć zwykłego użytkownika lub superużytkownika

#!/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 i --password nie są obowiązkowe.

Jeśli opcja --superuser nie jest zdefiniowana, zostanie utworzony zwykły użytkownik Jeśli --password nie jest zdefiniowane, zostanie wygenerowane hasło losowe

    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
źródło
0

Oto, co zebrałem razem dla Heroku post_deploy i wstępnie zdefiniowanej zmiennej app.json :

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

Dzięki temu możesz mieć jedną zmienną env:

CREATE_SUPER_USER=admin:admin@example.com:password

Podoba mi się opcja shell --command , ale nie jestem pewien, jak uzyskać znak nowego wiersza w skrypcie poleceń. Bez znaku nowej linii ifwyrażenie powoduje błąd składni.

Janusz Skonieczny
źródło
0

Przejdź do wiersza poleceń i wpisz:

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

jeśli nie zostanie wykonana migracja, przejdź do folderu aplikacji django i wykonaj następujące czynności

  1. python manage.py migrate
  2. python manage.py createduperuser

potem bingo.

Arif Khan
źródło
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
źródło
0

Z shell_plus jest to o wiele łatwiejsze

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

Jak wspominali inni, z Django 3.0 możesz przekazać referencje poprzez zmienne środowiskowe. Jednak to podejście jest znacznie bardziej elastyczne, ponieważ pozwala na wykonanie innych bardziej skomplikowanych zadań, takich jak usunięcie wszystkich użytkowników testów itp.

Pithikos
źródło