如何在Django Admin面板创建非管理员用户时实现密码加密存储?
嘿,作为Django新手能想到用Admin来管理用户已经很棒啦!关于密码加密的问题,其实不用自己从零实现,Django自带的用户认证框架已经帮我们搞定了,我给你两种简单可行的方案,你可以根据自己的需求选:
方案1:用自定义用户模型(推荐,复用Django认证功能)
Django默认的User模型已经内置了密码加密、权限管理等功能,我们可以通过继承AbstractUser来扩展出自己的用户模型,这样既能区分不同类型的用户,又能自动实现密码加密。
步骤1:修改models.py
创建一个继承自AbstractUser的自定义用户模型,添加一个user_type字段来区分用户类型,以后要加其他字段直接在这个模型里加就行:
from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): # 定义用户类型选项 USER_TYPE_CHOICES = ( ('type1', 'User Type 1'), ('normal', 'Normal User'), ) user_type = models.CharField(max_length=10, choices=USER_TYPE_CHOICES, default='normal') def __str__(self): return self.username
步骤2:配置settings.py
告诉Django使用我们的自定义用户模型,在settings.py末尾添加:
AUTH_USER_MODEL = '你的应用名.CustomUser' # 比如你的app叫myapp,就写'myapp.CustomUser'
步骤3:迁移数据库
因为修改了核心的用户模型,需要重新生成迁移文件并执行迁移:
python manage.py makemigrations python manage.py migrate
步骤4:修改admin.py
注册自定义用户模型,并且配置Admin的显示和编辑字段,让它和默认的用户Admin一样好用:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import CustomUser class CustomUserAdmin(UserAdmin): # 列表页显示的字段 list_display = ('username', 'email', 'user_type', 'is_staff') # 添加用户时的字段组(支持密码确认) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2', 'user_type', 'email'), }), ) # 编辑用户时的字段组 fieldsets = ( (None, {'fields': ('username', 'password')}), ('个人信息', {'fields': ('first_name', 'last_name', 'email', 'user_type')}), ('权限设置', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}), ('重要日期', {'fields': ('last_login', 'date_joined')}), ) admin.site.register(CustomUser, CustomUserAdmin)
这样设置后,你在Admin里创建用户时,输入的密码会自动加密存储,和默认的管理员用户完全一样,而且可以通过user_type轻松区分不同类型的用户,未来扩展字段也非常方便。
方案2:给现有模型添加密码加密逻辑(不想改模型结构时用)
如果坚持要保留UserType1和NormalUser两个独立模型,我们可以通过重写模型的save方法,调用Django的哈希函数来加密密码:
修改models.py
from django.contrib.auth.hashers import make_password from django.db import models class UserType1(models.Model): Username = models.CharField(max_length=50, null=False, unique=True) # 加密后的密码长度较长,把max_length改成128 Password = models.CharField(max_length=128, null=False) class Meta: ordering = ('Username',) def __str__(self): return self.Username def save(self, *args, **kwargs): # 检查密码是否已经加密(Django加密后的密码以pbkdf2_sha256$开头) if not self.Password.startswith('pbkdf2_sha256$'): self.Password = make_password(self.Password) super().save(*args, **kwargs) class NormalUser(models.Model): Username = models.CharField(max_length=50, null=False, unique=True) Password = models.CharField(max_length=128, null=False) class Meta: ordering = ('Username',) def __str__(self): return self.Username def save(self, *args, **kwargs): if not self.Password.startswith('pbkdf2_sha256$'): self.Password = make_password(self.Password) super().save(*args, **kwargs)
这样每次在Admin里创建或修改用户时,明文密码都会自动加密后存入数据库。不过这个方案的缺点是,你没法直接用Django的认证系统(比如login视图、权限管理),如果以后需要用户登录功能,得自己写认证逻辑,所以还是更推荐方案1。
内容的提问来源于stack exchange,提问作者Joselu
相关产品推荐
相关产品推荐

