在Django REST Framework及管理面板中将邮箱设为主键的问题
Hey there! Let's break down and solve your two Django/DRF problems step by step:
问题1:将邮箱作为用户模型的主键
Django自带的auth.User模型默认用自增id作为主键,要改成用邮箱作为主键,你需要自定义用户模型——因为默认的User模型是不能直接修改主键字段的。这里是具体实现步骤:
1. 定义自定义用户模型和管理器
在你的app的models.py中添加以下代码:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin # 自定义用户管理器,处理用户创建逻辑 class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError("Email is a required field!") # 标准化邮箱格式(比如转小写) email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): # 超级用户必须拥有staff和superuser权限 extra_fields.setdefault("is_staff", True) extra_fields.setdefault("is_superuser", True) if extra_fields.get("is_staff") is not True: raise ValueError("Superuser must have is_staff=True") if extra_fields.get("is_superuser") is not True: raise ValueError("Superuser must have is_superuser=True") return self.create_user(email, password, **extra_fields) # 自定义用户模型,用email作为主键 class CustomUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True, primary_key=True) # 设置为主键 first_name = models.CharField(max_length=50, blank=True) last_name = models.CharField(max_length=50, blank=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) objects = CustomUserManager() # 指定登录时用邮箱作为标识 USERNAME_FIELD = "email" # 创建超级用户时不需要额外必填字段(email已经是USERNAME_FIELD) REQUIRED_FIELDS = [] def __str__(self): return self.email
2. 配置Django使用自定义用户模型
在项目根目录的settings.py中添加一行,告诉Django使用你的自定义模型:
AUTH_USER_MODEL = "your_app_name.CustomUser" # 替换成你的app名称
重要提醒
如果你的项目已经有过数据库迁移(比如执行过makemigrations或migrate),最好重置数据库(备份数据后):
- 删除所有app下
migrations文件夹里除了__init__.py的文件 - 删除数据库文件(比如sqlite的db.sqlite3)
- 重新执行
python manage.py makemigrations和python manage.py migrate
问题2:解决管理站点的外键约束错误
这个1452错误的核心意思是:你创建ResearchProject时,指定的lead_researcher_id在关联的用户表中找不到对应的记录,导致外键约束失败。下面是常见原因和解决方法:
原因1:外键关联了错误的用户模型
如果你已经自定义了用户模型,但ResearchProject的外键还是指向默认的auth.User,就会出现这个问题。修改你的项目模型:
from django.db import models from django.conf import settings class ResearchProject(models.Model): lead_researcher = models.ForeignKey( settings.AUTH_USER_MODEL, # 动态关联当前配置的用户模型 on_delete=models.CASCADE, related_name="research_projects" ) # 其他字段...
原因2:管理站点配置问题
检查你的admin.py,确保lead_researcher字段是可选择的下拉框,并且显示的是存在的用户:
from django.contrib import admin from .models import ResearchProject class ResearchProjectAdmin(admin.ModelAdmin): # 确保lead_researcher在列表和表单中正常显示 list_display = ("project_name", "lead_researcher") fields = ("project_name", "lead_researcher", ...) # 包含lead_researcher字段 admin.site.register(ResearchProject, ResearchProjectAdmin)
原因3:数据库存在脏数据
如果数据库里已有ResearchProject记录,它们的lead_researcher_id可能指向了已删除的用户。可以通过Django Shell修复:
- 打开Shell:
python manage.py shell - 执行以下代码清理无效记录:
from django.conf import settings from your_app_name.models import ResearchProject # 获取所有lead_researcher不存在的项目 invalid_projects = ResearchProject.objects.filter( lead_researcher__isnull=False ).exclude( lead_researcher__in=settings.AUTH_USER_MODEL.objects.all() ) # 可以选择删除这些无效项目,或者重新分配给存在的用户 invalid_projects.delete()
原因4:迁移未正确执行
如果刚修改了用户模型或外键关联,确保重新执行迁移:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Lior Alon
相关产品推荐
相关产品推荐

