Como automatizar o createuperuser no django?

128

Quero auto run manage.py createsuperuseron djangomas nas encostas que não há nenhuma maneira de definir uma senha padrão.

Como posso conseguir isso? Ele deve ser independente no banco de dados django.

Bogdan
fonte
1
você procurou apenas salvar o superusuário criado em um equipamento e carregá-lo usando o manage.py?
turbotux
1
A resposta do @turbotux Hendrik F segue uma abordagem semelhante à sugerida, com a capacidade adicional de ler os valores (login, senha ...) dos env vars (ou sistema de arquivos, ...). Eu sugiro ir nessa direção em vez dos scripts ad-hoc python, que têm problemas quando você reinicia o aplicativo.
Ad N

Respostas:

145

Se você referenciar o usuário diretamente, seu código não funcionará em projetos nos quais a configuração AUTH_USER_MODEL foi alterada para um modelo de usuário diferente. Uma maneira mais genérica de criar o usuário seria:

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

RESPOSTA ORIGINAL

Aqui está uma versão simples do script para criar um superusuário:

echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', '[email protected]', 'pass')" | python manage.py shell
Tk421
fonte
2
super útil ao tentar criar superusuário no heroku e sua rede bloqueia a porta 5000
Vic
4
Eu iria apagar o superusuário existente, de modo que este é válido para cada compilação: 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
Pessoalmente, não acho que excluir o usuário em cada build seja uma boa ideia. Você corre o risco de excluir acidentalmente quaisquer registros associados por meio de uma exclusão em cascata. Uma opção mais segura é simplesmente resgatar se o usuário já existe (ou atualizar o registro existente do usuário).
Will
6
Pelo menos no Django 1.11. a ordem dos argumentos é ('nome de usuário', 'email', 'aprovação'), não ('email', 'nome de usuário', 'aprovação'). Veja: docs.djangoproject.com/en/1.11/ref/contrib/auth/…
np8
3
from django.contrib.auth.models import Usernão funciona mais. Use isto: from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('admin', '[email protected]', 'my secure password')
dcalde 10/06
49

Eu mesmo estava procurando uma resposta para isso. Eu decidi criar um comando Django que estende o createsuperusercomando 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()

Exemplo de uso:

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

Isso tem a vantagem de ainda suportar o uso padrão do comando, além de permitir o uso não interativo para especificar uma senha.

Adam Charnock
fonte
4
Essa deve ser a resposta mais votada (e aceita).
Bruno desthuilliers
Gostaria que o padrão createsuperusertinha esse --passwordcampo também
shadi
1
Você pode adicionar um exemplo de uso:./manage.py createsuperuser2 --username test1 --password 123321 --noinput --email '[email protected]'
shadi
2
como é createsuperuser2mapeado para esta classe, função
Srinath Ganesh
2
@SrinathGanesh consulte docs.djangoproject.com/en/1.8/howto/custom-management-commands Você precisa nomear o arquivo python createsuperuser2.pye colocá-lo na estrutura de diretórios definida no link acima.
ElectRocnic 23/09
43

Eu uso './manage.py shell -c':

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

Isso não usa um eco extra; isso tem o benefício de que você pode transmiti-lo para um contêiner de docker para execução. Sem a necessidade de usar sh -c "..." que o leva a citar escapando do inferno.

E lembre-se de que primeiro vem o nome de usuário, do que o email.

Se você possui um modelo de usuário personalizado, é necessário importá-lo e não auth.models.User

yvess
fonte
1
Trabalhou para mim. Obrigado!
TimH - Codidact
Não parece trabalhar para mim, eu estou vendo:AttributeError: Manager isn't available; 'auth.User' has been swapped for 'users.User'
Brodan
quando você tem um modelo de usuário personalizado, como users.User você precisa importar a partir dele e não a partir deauth.User
yvess
30

Eu sugeriria a execução de uma migração de dados ; portanto, quando as migrações são aplicadas ao projeto, um superusuário é criado como parte das migrações. O nome de usuário e a senha podem ser configurados como variáveis ​​de ambiente. Isso também é útil ao executar um aplicativo em um contêiner (veja este tópico como um exemplo)

Sua migração de dados ficaria assim:

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

Espero que ajude!

EDIT : Alguns podem levantar a questão de como definir essas variáveis ​​de ambiente e tornar o Django ciente delas. Existem várias maneiras e isso foi respondido em outras postagens do SO, mas, como um ponteiro rápido, criar um .envarquivo é uma boa idéia. Você pode usar o pacote python-dotenv , mas se você configurou um ambiente virtual com o pipenv, ele definirá automaticamente os envvars no seu .envarquivo. Da mesma forma, a execução do aplicativo via docker-compose pode ser lida no seu .envarquivo.

Hendrik F
fonte
1
DICA: Por favor, considere esta abordagem . Esta é uma resposta de alta qualidade: ela naturalmente aproveita as funcionalidades internas do Django para responder à pergunta em vez de repetir scripts python ad-hoc, além de tratar naturalmente do maior problema da resposta aceita (a migração é aplicada apenas uma vez em uma implantação , para que o usuário seja criado apenas uma vez). Funciona lindamente em um contexto de contêiner.
Ad N
Esta parece ser uma ótima resposta. Ainda não sei em que parte do projeto esse código se encaixa?
Pablo Ruiz Ruiz
Ele deve estar em sua pasta migrações, por exemplo root/⁨mysite⁩/myapp⁩/⁨migrations⁩- se o seu ler os docs, ele explica como você pode criar uma migração vazio e modificar essepython manage.py makemigrations --empty yourappname
Hendrik F
Por que você precisa do DJANGO_DB_NAME? nunca é usado.
thoroc 13/06
Você deve mencionar para adicionar o seguinte para carregar os vars .env no settings.pyarquivo:python # loading .env from dotenv import load_dotenv from pathlib import Path env_path = Path('.', '.env') load_dotenv(dotenv_path=env_path)
thoroc
22

A partir de Django 3.0, você pode usar o padrão createsuperuser --noinputde comando e defina todos os campos obrigatórios (incluindo senha) como variáveis de ambiente DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_EMAILpor exemplo. --noinputsinalizador é obrigatório.

Isso vem dos documentos originais: https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-createsuperuser

e acabei de verificar - funciona. Agora você pode exportar facilmente esses vars de ambiente e adicionar createsuperuserseus scripts e pipelines.

Alexey Trofimov
fonte
14

Você pode escrever um script python simples para lidar com a automação da criação de superusuário. O Usermodelo é apenas um modelo normal do Django, então você deve seguir o processo normal de escrever um script Django independente. 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()

Você também pode passar createsuperuseralgumas opções, a saber, --noinpute --username, que permitiriam criar automaticamente novos superusuários, mas eles não seriam capazes de efetuar login até você definir uma senha para eles.

zeekay
fonte
2
Ok cretesuperuser, mas como definir a senha? Eu gostaria de fazer isso dentro de um script bash ...
caneta
10

Resposta mais votada atual:

  • Exclui o usuário, se houver, e conforme observado por @Groady nos comentários, você corre o risco de excluir acidentalmente quaisquer registros associados por meio de uma exclusão em cascata.
  • Verifica a existência do superusuário filtrando por e-mail, se dois superusuários tiverem o mesmo e-mail, ele saberá qual deles será excluído.
  • É complicado atualizar os parâmetros do script: nome de usuário, senha e email.
  • Não registra o que fez.

Uma versão melhorada seria:

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
fonte
2
Muito mais limpo (melhor) que a resposta aceita. Você também poderia ter usado: if not User.objects.filter(username = username).exists(),
Philippe Fanaro
5
DJANGO_SUPERUSER_USERNAME=testuser \
DJANGO_SUPERUSER_PASSWORD=testpass \
python manage.py createsuperuser --noinput

Documentação para o comando createuser

Rafal Enden
fonte
Esta é a solução mais fácil. Mas você pode substituir a noinputbandeira com outros parâmetros:DJANGO_SUPERUSER_PASSWORD=testpass python manage.py createsuperuser --username testuser --email [email protected] --noinput
dannydedog 23/06
1

Eu usei o Tk421 em uma linha, mas recebi uma mensagem de erro como: 1) Acho que estou usando uma versão posterior do Django (1.10) Manager isn't available; 'auth.User' has been swapped for 'users.User'2) a ordem dos parâmetros para create_superuser estava errada.

Então substituí-o por:

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

e o que mais me agradou é que ele também funciona em uma implantação 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

Isso funcionará bem repetidamente. Estou usando-o no início de um projeto, portanto, não se preocupe com as terríveis exclusões em cascata que podem ocorrer mais tarde.

Eu revisitei após alguns problemas com a execução deste local dentro () do fabric. o que parecia estar acontecendo é que o símbolo do cachimbo significa que estava sendo interpretado localmente, e não no heroku. Para classificar isso, envolvi o comando entre aspas. Em seguida, teve que usar aspas duplas triplas para as seqüências de caracteres python dentro das aspas simples de todo o comando 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
fonte
1

Uma solução baseada na abordagem de Adam Charnock acima já está disponível como um pacote Python. São necessários três passos:

  1. Instalar: pip install django-createsuperuserwithpassword

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

  3. Aplique:

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

É isso aí.

Sebastian
fonte
0

Esse pequeno script python pode criar um usuário normal ou um superusuário

#!/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 e --password não são obrigatórios.

Se --superuser não estiver definido, o usuário normal será criado. Se --password não estiver definido, uma senha aleatória será gerada

    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
fonte
0

Isto é o que eu juntei para Heroku post_deploy e uma variável app.json predefinida :

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

Com isso, você pode ter uma única variável env:

CREATE_SUPER_USER=admin:admin@example.com:password

Eu gosto da opção shell --command , mas não sei como o caractere get newline no script de comando. Sem a nova linha, a ifexpressão resulta em erro de sintaxe.

Janusz Skonieczny
fonte
0

Vá para o prompt de comando e digite:

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

se não executou a migração, vá para a pasta do aplicativo django e execute as seguintes

  1. python manage.py migrate
  2. python manage.py cria superusuário

depois bingo.

Arif Khan
fonte
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
fonte
0

Com shell_plus é muito mais fácil, na verdade

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

Como outros mencionados, no Django 3.0 você pode passar as credenciais através de variáveis ​​de ambiente. No entanto, essa abordagem é muito mais flexível, pois permite executar qualquer outra tarefa mais complicada, como remover todos os usuários de testes, etc.

Pithikos
fonte