基于Django REST Framework自定义用户模型的密码创建求助
解决员工注册添加密码的两种方案
方案一:关联Django内置User模型(推荐)
Django自带的User模型已经封装了密码加密、登录认证等成熟功能,适合快速实现注册登录逻辑,步骤如下:
1. 修改Employee模型,关联User
给Employee添加一对一关联到User,复用User的密码、用户名字段:
from django.db import models from django.contrib.auth.models import User class Employee(models.Model): # 关联内置User模型,删除员工时同时删除关联的User user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee') name = models.CharField(max_length=50, unique=True, verbose_name='Name') email = models.EmailField(verbose_name='Email') department = models.CharField(max_length=30, verbose_name='Departamento') # 其他自定义字段... def __str__(self): return self.name
2. 编写注册专用序列化器
创建包含User和Employee字段的序列化器,处理密码加密和双模型创建:
from rest_framework import serializers from django.contrib.auth.models import User from .models import Employee class EmployeeRegistrationSerializer(serializers.Serializer): # User模型字段(登录用) username = serializers.CharField(max_length=150) password = serializers.CharField(write_only=True) # 只写字段,不返回给前端 # Employee自定义字段 name = serializers.CharField(max_length=50) email = serializers.EmailField() department = serializers.CharField(max_length=30) # 其他Employee字段... def create(self, validated_data): # 用create_user自动加密密码,创建User实例 user = User.objects.create_user( username=validated_data['username'], password=validated_data['password'] ) # 创建关联的Employee实例 employee = Employee.objects.create( user=user, name=validated_data['name'], email=validated_data['email'], department=validated_data['department'] # 赋值其他自定义字段 ) return employee
3. 编写注册视图
用DRF的CreateAPIView快速实现注册接口:
from rest_framework.generics import CreateAPIView from .serializers import EmployeeRegistrationSerializer class EmployeeRegistrationView(CreateAPIView): serializer_class = EmployeeRegistrationSerializer
4. 配置路由
在urls.py中添加注册接口路由:
from django.urls import path from .views import EmployeeRegistrationView urlpatterns = [ path('register/', EmployeeRegistrationView.as_view(), name='employee-register'), # 其他路由... ]
登录适配
注册完成后,直接用DRF内置的obtain_auth_token接口实现登录拿token:
# urls.py中添加 from rest_framework.authtoken.views import obtain_auth_token urlpatterns += [ path('login/', obtain_auth_token, name='employee-login'), ]
方案二:给Employee直接添加密码字段
如果不想依赖内置User模型,可以直接给Employee加密码字段,手动处理加密逻辑:
1. 修改Employee模型
添加密码字段,并在保存时自动加密:
from django.db import models from django.contrib.auth.hashers import make_password class Employee(models.Model): name = models.CharField(max_length=50, unique=True, verbose_name='Name') email = models.EmailField(verbose_name='Email') department = models.CharField(max_length=30, verbose_name='Departamento') password = models.CharField(max_length=128) # 存储哈希后的密码,长度设为128足够 # 其他自定义字段... def save(self, *args, **kwargs): # 仅当密码未加密时进行加密(避免更新时重复加密) if self.password and not self.password.startswith('pbkdf2_sha256$'): self.password = make_password(self.password) super().save(*args, **kwargs) def __str__(self): return self.name
2. 编写注册序列化器
设置密码为只写字段,避免返回给前端:
from rest_framework import serializers from .models import Employee class EmployeeRegistrationSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) class Meta: model = Employee fields = ['name', 'email', 'department', 'password'] # 包含其他自定义字段 def create(self, validated_data): # 模型save方法已处理加密,直接创建实例 return Employee.objects.create(**validated_data)
3. 自定义认证后端(用于登录)
因为没有用内置User,需要自定义认证逻辑:
# 在app下创建backends.py from django.contrib.auth.backends import BaseBackend from .models import Employee from django.contrib.auth.hashers import check_password class EmployeeAuthBackend(BaseBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: # 这里假设用name作为登录用户名,可根据需求改成email employee = Employee.objects.get(name=username) # 验证密码哈希 if check_password(password, employee.password): return employee except Employee.DoesNotExist: return None def get_user(self, user_id): try: return Employee.objects.get(pk=user_id) except Employee.DoesNotExist: return None
4. 配置认证后端
在settings.py中添加自定义后端:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'your_app_name.backends.EmployeeAuthBackend', # 替换为你的app路径 ]
内容的提问来源于stack exchange,提问作者orange freeze
相关产品推荐
相关产品推荐

