You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中将模型转为用户?迁移遇唯一约束错误求助

驾照管理Web应用用户模型问题排查与解决

问题背景

开发驾照管理Web应用作业时,希望将驾驶员信息作为Django用户管理,于是将Car_owner模型继承AbstractUser,但执行迁移时出现以下错误:

UNIQUE constraint failed: new__project_first_app_car_owner.username

相关代码如下:

models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class Car_owner(AbstractUser):
    id_owner = models.IntegerField(primary_key=True)
    last_name = models.CharField(max_length=30, null=False)
    first_name = models.CharField(max_length=30, null=False)
    birth_date = models.DateField(null=True)
    passport = models.IntegerField(null=True, blank=True)
    address = models.CharField(max_length=50, null=True, blank=True)
    nationality = models.CharField(max_length=15, null=True, blank=True)

    # username = models.CharField(max_length=16, unique=True, default=uuid4)
    # password = models.CharField(max_length=16, default='password')

forms.py

from django import forms
from project_first_app.models import Car_owner

class CreateOwner(forms.ModelForm):
    class Meta:
        model = Car_owner
        fields = ['id_owner', 'last_name', 'first_name', 'birth_date', 'passport', 'address', 'nationality']

迁移文件自动生成了以下内容:

migrations.AddField(
    model_name='car_owner',
    name='username',
    field=models.CharField(default=uuid.uuid4, max_length=16, unique=True),
),
migrations.AlterField(
    model_name='car_owner',
    name='username',
    field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username'),
),

错误原因

  1. 未配置自定义用户模型:继承AbstractUser后必须在settings.py中指定AUTH_USER_MODEL,否则Django会同时维护默认User模型和自定义模型,导致字段冲突。
  2. 主键字段冲突:AbstractUser自带id主键,自定义的id_owner主键与父类主键重复,引发数据库约束异常。
  3. 必填字段缺失:username是AbstractUser的必填唯一字段,表单未包含该字段,导致用户创建时无法生成合法值,触发唯一约束失败。

解决步骤

1. 配置自定义用户模型

在项目根目录的settings.py中添加:

AUTH_USER_MODEL = 'project_first_app.Car_owner'

注意:如果已经执行过迁移,需要清理旧迁移文件和数据库(开发环境下可直接删除db.sqlite3),因为Django对用户模型的更改不支持后续修改。

2. 修正模型字段

去掉自定义的id_owner主键,使用AbstractUser自带的id主键,同时无需手动定义username和password(父类已包含):

# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models

class Car_owner(AbstractUser):
    last_name = models.CharField(max_length=30, null=False)
    first_name = models.CharField(max_length=30, null=False)
    birth_date = models.DateField(null=True)
    passport = models.IntegerField(null=True, blank=True)
    address = models.CharField(max_length=50, null=True, blank=True)
    nationality = models.CharField(max_length=15, null=True, blank=True)

3. 清理旧迁移并重新生成

  1. 删除project_first_app/migrations目录下除__init__.py外的所有文件
  2. 清空开发数据库(如删除db.sqlite3)
  3. 重新执行迁移:
python manage.py makemigrations
python manage.py migrate

4. 修正表单字段

将username添加到表单字段中,确保用户创建时能填写或生成合法的唯一用户名:

# forms.py
from django import forms
from project_first_app.models import Car_owner

class CreateOwner(forms.ModelForm):
    class Meta:
        model = Car_owner
        fields = ['username', 'last_name', 'first_name', 'birth_date', 'passport', 'address', 'nationality']

额外建议

  • 如果希望用其他字段(如手机号)代替username作为登录标识,可以在模型中设置USERNAME_FIELD = 'passport'(需确保该字段唯一且非空)
  • 开发初期就确定用户模型结构,避免后续修改带来的迁移问题

内容的提问来源于stack exchange,提问作者Constantine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 11:15:39