Comment automatiser createuperuser sur django?

128

Je veux démarrer automatiquement manage.py createsuperuser, djangomais il semble qu'il n'y a aucun moyen de définir un mot de passe par défaut.

Comment puis-je l'obtenir? Il doit être indépendant de la base de données django.

Bogdan
la source
1
avez-vous simplement envisagé de sauvegarder votre superutilisateur créé un appareil et de le charger à l'aide de manage.py?
turbotux
1
@turbotux Hendrik F answer adopte une approche similaire à ce que vous suggérez, avec la possibilité supplémentaire de lire les valeurs (login, mot de passe ...) depuis les variables d'environnement (ou système de fichiers, ...). Je suggérerais fortement d'aller dans cette direction au lieu des scripts python ad hoc, qui rencontrent des problèmes lorsque vous redémarrez l'application.
Annonce N du

Réponses:

145

Si vous référencez l' utilisateur directement, votre code ne fonctionnera pas dans les projets où le paramètre AUTH_USER_MODEL a été remplacé par un modèle utilisateur différent. Une manière plus générique de créer l'utilisateur serait:

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

RÉPONSE ORIGINALE

Voici une version simple du script pour créer un superutilisateur:

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | python manage.py shell
Tk421
la source
2
super utile lorsque vous essayez de créer un super-utilisateur dans heroku et que votre réseau bloque le port 5000
Vic
4
Je supprimerais le superutilisateur existant, donc ceci est valable pour chaque build: 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
Personnellement, je ne pense pas que la suppression de l'utilisateur sur chaque build soit une bonne idée. Vous risquez de supprimer involontairement les enregistrements associés via une suppression en cascade. Une option plus sûre consiste simplement à renflouer si l'utilisateur existe déjà (ou à mettre à jour l'enregistrement utilisateur existant).
Sera le
6
Au moins sur Django 1.11. l'ordre des arguments est ('username', 'email', 'pass'), pas ('email', 'username', 'pass'). Voir: docs.djangoproject.com/en/1.11/ref/contrib/auth/…
np8
3
from django.contrib.auth.models import Userne fonctionne plus. Utilisez ceci: from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'my secure password')
dcalde
49

Je cherchais moi-même une réponse à cela. J'ai décidé de créer une commande Django qui étend la createsuperusercommande de 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()

Exemple d'utilisation:

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

Cela présente l'avantage de toujours prendre en charge l'utilisation de la commande par défaut, tout en permettant une utilisation non interactive pour la spécification d'un mot de passe.

Adam Charnock
la source
4
Cela devrait être la réponse la plus positive (et acceptée).
bruno desthuilliers
Je souhaite que la valeur par défaut createsuperuserait aussi ce --passwordchamp
shadi
1
Vous pouvez ajouter un exemple d'utilisation:./manage.py createsuperuser2 --username test1 --password 123321 --noinput --email '[email protected]'
shadi
2
comment est createsuperuser2mappé à cette classe, fonction
Srinath Ganesh
2
@SrinathGanesh jetez un œil à docs.djangoproject.com/en/1.8/howto/custom-management-commands Vous devez nommer le fichier python createsuperuser2.pyet le placer dans la structure de répertoire définie à partir du lien ci-dessus.
ElectRocnic
43

J'utilise './manage.py shell -c':

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

Cela n'utilise pas d'écho supplémentaire, cela présente l'avantage de pouvoir le transmettre à un conteneur docker pour exécution. Sans avoir besoin d'utiliser sh -c "..." ce qui vous amène à échapper à l'enfer.

Et rappelez-vous que le nom d'utilisateur vient en premier , plutôt que l'e-mail.

Si vous avez un modèle utilisateur personnalisé, vous devez l'importer et non auth.models.User

yvess
la source
1
A travaillé pour moi. Merci!
TimH - Codidact
Ne semble pas fonctionner pour moi, je vois:AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'
Brodan
lorsque vous avez un modèle utilisateur personnalisé comme users.User vous devez importer de celui-ci et non deauth.User
yvess
30

Je suggérerais d'exécuter une migration de données , donc lorsque les migrations sont appliquées au projet, un superutilisateur est créé dans le cadre des migrations. Le nom d'utilisateur et le mot de passe peuvent être configurés en tant que variables d'environnement. Ceci est également utile lors de l'exécution d'une application dans un conteneur (voir ce fil à titre d'exemple)

Votre migration de données ressemblerait alors à ceci:

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

J'espère que cela pourra aider!

EDIT : Certains pourraient soulever la question de savoir comment définir ces variables d'environnement et en informer Django. Il existe de nombreuses façons et cela a été répondu dans d'autres articles SO, mais juste comme un pointeur rapide, la création d'un .envfichier est une bonne idée. Vous pouvez alors utiliser le package python-dotenv , mais si vous avez configuré un environnement virtuel avec pipenv, il définira automatiquement les envvars dans votre .envfichier. De même, l'exécution de votre application via docker-compose peut lire votre .envfichier.

Hendrik F
la source
1
CONSEIL: Veuillez considérer cette approche . C'est une réponse de haute qualité: elle exploite naturellement les fonctionnalités intégrées de Django pour répondre à la question au lieu de faire écho aux scripts python ad-hoc, et elle résout naturellement le plus gros problème de la réponse acceptée (une migration n'est appliquée qu'une seule fois sur un déploiement , de sorte que l'utilisateur n'est créé qu'une seule fois). Cela fonctionne à merveille dans un contexte de conteneur.
Annonce N du
Cela semble une excellente réponse. Je ne sais toujours pas où dans le projet ce morceau de code s'inscrit?
Pablo Ruiz Ruiz
Il devrait être dans votre dossier de migrations, par exemple root/⁨mysite⁩/myapp⁩/⁨migrations⁩- si vous lisez la documentation, cela explique comment vous pouvez créer une migration vide et la modifierpython manage.py makemigrations --empty yourappname
Hendrik F
Pourquoi avez-vous besoin de DJANGO_DB_NAME? il n'est jamais utilisé.
thoroc le
Vous devez mentionner d'ajouter ce qui suit pour charger les variables .env dans le settings.pyfichier: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 , vous pouvez utiliser par défaut createsuperuser --noinputcommande et définir tous les champs obligatoires (y compris le mot de passe) comme variables d'environnement DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAILpar exemple. --noinputdrapeau est requis.

Cela vient des documents originaux: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-createsuperuser

et je viens de vérifier - cela fonctionne. Vous pouvez désormais exporter facilement ces variables d'environnement et les ajouter createsuperuserà vos scripts et pipelines.

Alexey Trofimov
la source
14

Vous pouvez écrire un simple script python pour gérer l'automatisation de la création des super-utilisateurs. Le Usermodèle est juste un modèle Django normal, vous suivrez donc le processus normal d'écriture d'un script Django autonome. 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()

Vous pouvez également passer createsuperuserquelques options, à savoir --noinputet --username, qui vous permettraient de créer automatiquement de nouveaux super-utilisateurs, mais ils ne pourraient pas se connecter tant que vous ne leur aurez pas défini un mot de passe.

Zeekay
la source
2
Ok pour cretesuperuser, mais comment définir le mot de passe alors? Je voudrais faire cela dans un script bash ...
caneta
10

Réponse la plus votée actuelle:

  • Supprime l'utilisateur s'il existe et comme indiqué par @Groady dans les commentaires, vous risquez de supprimer involontairement les enregistrements associés via une suppression en cascade.
  • Vérifie le filtrage de l'existence des super-utilisateurs par courrier, donc si deux super-utilisateurs ont le même courrier, Dieu sait lequel il supprime.
  • Il est difficile de mettre à jour les paramètres du script: nom d'utilisateur, mot de passe et courrier.
  • N'enregistre pas ce qu'il a fait.

Une version améliorée serait:

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
la source
2
Beaucoup plus propre (mieux) que la réponse acceptée. Vous pouvez également avoir utilisé: if not User.objects.filter(username = username).exists(),
Philippe Fanaro
5
DJANGO_SUPERUSER_USERNAME=testuser \
DJANGO_SUPERUSER_PASSWORD=testpass \
python manage.py createsuperuser --noinput

Documentation de la commande createuser

Rafal Enden
la source
C'est la solution la plus simple. Mais vous pouvez écraser le noinputdrapeau avec d'autres paramètres:DJANGO_SUPERUSER_PASSWORD=testpass python manage.py createsuperuser --username testuser --email [email protected] --noinput
dannydedog
1

J'ai utilisé une doublure Tk421 mais j'ai reçu un message d'erreur comme: 1) Je pense que j'utilise une version ultérieure de Django (1.10) Manager isn't available; 'auth.User' has been swapped for 'users.User'2) l'ordre des paramètres à create_superuser était incorrect.

Alors je l'ai remplacé par:

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

et ce qui me plaît vraiment, c'est que cela fonctionne également sur un déploiement 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

Cela fonctionnera bien à plusieurs reprises. Je l'utilise au début d'un projet, alors ne vous inquiétez pas des terribles suppressions en cascade qui pourraient survenir plus tard.

J'ai revisité après quelques problèmes avec l'exécution de ceci dans local () à partir de fabric. ce qui semblait se passer, c'est que le symbole du tuyau signifiait qu'il était interprété localement plutôt que sur heroku. Pour trier cela, j'ai enveloppé la commande entre guillemets. Ensuite, j'ai dû utiliser des guillemets doubles triples pour les chaînes python à l'intérieur des guillemets simples de toute la commande 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
la source
1

Une solution basée sur l' approche d' Adam Charnock ci - dessus est désormais disponible sous forme de package Python. Cela prend trois étapes:

  1. Installer: pip install django-createsuperuserwithpassword

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

  3. Appliquer:

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

C'est tout.

Sébastien
la source
0

Ce petit script python pourrait créer un utilisateur normal ou un superutilisateur

#!/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 ne sont pas obligatoires.

Si --superuser n'est pas défini, l'utilisateur normal sera créé Si --password n'est pas défini, un mot de passe aléatoire sera généré

    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
la source
0

C'est ce que j'ai bricolé pour Heroku post_deploy et une variable app.json prédéfinie :

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

Avec cela, vous pouvez avoir une seule variable d'environnement:

CREATE_SUPER_USER=admin:admin@example.com:password

J'aime l' option shell --command , mais je ne sais pas comment obtenir le caractère de nouvelle ligne dans le script de commande. Sans la nouvelle ligne, l' ifexpression entraîne une erreur de syntaxe.

Janusz Skonieczny
la source
0

Accédez à l'invite de commande et tapez:

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 la migration n'a pas été exécutée, allez dans le dossier de l'application django et exécutez ce qui suit

  1. python manage.py migrer
  2. python manage.py créeuperuser

puis bingo.

Arif Khan
la source
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
la source
0

Avec shell_plus, c'est beaucoup plus facile en fait

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

Comme d'autres l'ont mentionné, avec Django 3.0, vous pouvez transmettre les informations d'identification via des variables d'environnement. Cependant, cette approche est beaucoup plus flexible car elle vous permet d'effectuer toute autre tâche plus compliquée comme la suppression de tous les utilisateurs de tests, etc.

Pithikos
la source