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

Django自定义User模型后外键约束报错:字段类型不匹配

Django外键关联报错:字段类型不匹配问题解决

问题场景

自定义User模型代码:

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    
    class Meta:
        app_label = "myapp"

关联该User模型的TestTable模型代码:

class TestTable(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    value = models.FloatField()

执行makemigrations和migrate时出现报错:

(3780, "Referencing column 'user_id' and referenced column 'id' in foreign key constraint")

查看数据库表结构:
myapp_user表的主键类型:

mysql> describe myapp_user;
+--------------+--------------+------+-----+---------+----------------+
| Field        | Type         | Null | Key | Default | Extra          |
+--------------+--------------+------+-----+---------+----------------+
| id           | int          | NO   | PRI | NULL    | auto_increment |
| ...          | ...          | ...  | ... | ...     | ...            |
+--------------+--------------+------+-----+---------+----------------+

myapp_testtable表的外键类型:

mysql> describe myapp_testtable;
+---------+--------+------+-----+---------+----------------+
| Field   | Type   | Null | Key | Default | Extra          |
+---------+--------+------+-----+---------+----------------+
| user_id | bigint | NO   |     | NULL    |                |
| ...     | ...    | ...  | ... | ...     | ...            |
+---------+--------+------+-----+---------+----------------+

问题原因

Django 3.2版本对默认主键类型做了变更:3.2之前的版本中,AbstractUser的主键默认使用AutoField(对应MySQL的int类型);而3.2及以后的版本,默认主键类型改为BigAutoField(对应MySQL的bigint类型)。

你的myapp_user表是基于旧版本Django创建的,主键为int;但当前使用的是新版本Django,新创建的TestTable模型的外键字段会自动采用新版本的默认主键类型bigint,两者类型不匹配,导致MySQL无法创建外键约束。

解决方法

方法一:修改User模型,统一主键类型为bigint

修改User模型,显式指定主键为BigAutoField:

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

class User(AbstractUser):
    id = BigAutoField(primary_key=True)
    
    class Meta:
        app_label = "myapp"

执行以下命令完成迁移:

python manage.py makemigrations
python manage.py migrate

此操作会将myapp_user表的id字段类型改为bigint,与TestTable的user_id类型匹配,外键约束可正常创建。

方法二:修改TestTable外键字段类型,匹配User表的int

如果不想改动已有的myapp_user表,可修改TestTable的外键字段,显式指定数据库类型为int:

from django.db import models
from django.conf import settings

class TestTable(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        db_type='int'
    )
    value = models.FloatField()

重新生成迁移并执行:

python manage.py makemigrations
python manage.py migrate

此操作会将TestTable的user_id字段改为int类型,与User表的主键类型一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 19:50:25