为什么要添加一个初始化超级用户的命令行入口
django提供了一系列重要而且好用的命令行工具,使用创建项目时自动生成的manage.py,
或者全局django-admin都可以运行这些程序。
python mamage.py
django-admin
其中在启用了django.contrib.auth
app之后,我们可以受用createsuperuser命令来创建超级用户。
python manage.py createsuperuser
这个命令通常时我们启用django身份验证功能之后要登录到admin站点必须要使用的命令。但是这个命令的
问题在于它只能用交互方式运行,我们无法用一个非交互式脚本来创建用户,比如我们的站点需要一键
安装、自动化搭建测试环境等等场景。
在使用命令行之外我们也有其他选项,比如在migrations增加一个创建默认超级用户的脚本,在安装过程中
执行migrate从而添加默认超级用户。但这样做的问题是默认用户信息在所有环境中都是相同的,如果管理人员
忘记修改默认密码,可能会导致安全风险。
如果有一个命令行能用无交互的方式,使用参数来指定超级用户的账号和密码,就会适应更多场景的要求。
如何实现
命令行接口的设计
我们需要一个命令行工具,用如下的方式创建一个超级用户。
python manage.py initadmin --user=admin --password=YourPassword --email=abc@example.com
这个命令行还能从环境变量中读取参数信息
DJANGO_SU_NAME=admin DJANGO_SU_PASSWORD=YourPassword DJANGO_SU_EMAIL=abc@example.com python manage.py initadmin
或者
export DJANGO_SU_NAME=admin
export DJANGO_SU_PASSWORD=YourPassword
export DJANGO_SU_EMAIL=abc@example.com
python manage.py initadmin
使用django custom django-admin commands框架
django提供了自行扩展命令行工具的框架,添加相关代码后可以直接采用manage.py或python-admin命令行进行调用。
相关文档可以参考!()[https://docs.djangoproject.com/en/3.0/howto/custom-management-commands/]
首先需要在自己的app中创建指定文件夹,django会从指定文件夹中加载相应模块,假设你的app名字为myapp,
command模块应在myapp/management/commands
文件夹下,
这两个文件夹都是package,因此别忘了在management
文件夹和commands
文件夹都添加__init__.py
文件,
在commands
包下添加initadmin
模块,即initadmin.py
# myapp/management/commands/initadmin.py
import os
from django.core.management.base import BaseCommand
from django.contrib.auth.models import User
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('--user')
parser.add_argument('--password')
parser.add_argument('--email')
def handle(self, *args, **options):
admin_username = options.get('user') or os.environ.get('DJANGO_SU_NAME')
admin_email = options.get('email') or os.environ.get('DJANGO_SU_EMAIL')
admin_password = options.get('password') or os.environ.get('DJANGO_SU_PASSWORD')
if not admin_username:
raise Exception("No username specified.")
if not admin_email:
raise Exception('No email specified.')
if not admin_password:
raise Exception('No password specified.')
if User.objects.filter(username=admin_username).first():
print(f'{admin_username} user already exists.')
return
admin_user = User.objects.create_superuser(username=admin_username,
email=admin_email,
password=admin_password)
admin_user.is_active = True
admin_user.is_admin = True
admin_user.save()
print(f'{admin_username} user created.')
使用
命令行使用
如前面提到的方式使用即可,可通过命令行参数指定admin用户信息,或者使用环境变量
DJANGO_SU_NAME=admin DJANGO_SU_PASSWORD=YourPassword DJANGO_SU_EMAIL=abc@example.com python manage.py initadmin
DJANGO_SU_NAME=admin DJANGO_SU_PASSWORD=YourPassword DJANGO_SU_EMAIL=abc@example.com python manage.py initadmin
在docker中使用
首先在entrypoint.sh 中增加检查选项,并根据选项运行命令行
# docker-entrypoint.sh
if [ "x$DJANGO_MANAGEPY_INITADMIN" = 'xon' ]; then
$PYTHON manage.py initadmin
fi
在docker运行时指定参数
docker run -e DJANGO_MANAGEPY_INITADMIN=on -e DJANGO_SU_NAME=admin -e DJANGO_SU_PASSWORD=YourPassword xxx
或者在docker-compose中指定参数
#docker-compose.yml
version: '3'
services:
web:
image: xxx
ports:
- "8000:8000"
environment:
DJANGO_MANAGEPY_INITADMIN: 'on'
DJANGO_SU_NAME: 'admin'
DJANGO_SU_PASSWORD: 'YourPassword'