Django解决ForeignKey引用外键时类型不匹配问题

本文详细阐述了如何在Django中处理外键引用时的类型不匹配问题,包括报错原因、迁移文件操作调整和配置文件设置,确保模型间的正确关联。

**

Django解决ForeignKey引用外键时类型不匹配问题(3780)

**

方法一:

**
**

1.报错的代码:

File "F:\pychrom_python\web\django\venv\meiduo_project_venv\lib\site-packages\pymysql\err.py", line 143, in raise_mysql_exception
    raise errorclass(errno, errval)
pymysql.err.OperationalError: (3780, "Referencing column 'xxx' and referenced column 'xxx' in foreign key constraint 'xxxx' are incompatible.")

2.报错的原因:

在一个模型中使用field_name=models.ForeignKey(‘models_name’)去创建一个外键字段的时候,在迁移模型的时候,django会在数据库表中创建一个field_name_id的字段,而该字段的类型与引用其他表中的主键的类型不匹配,所有在迁移的时候django会raise 3780出来.

3.查看当前迁移文件时生成的sql命令

使用终端中使用python manage.py sqlmigrate <app_name> <migration>查看当前迁移文件所产生的sql语句

在这里插入图片描述当前迁移创建的外键字段类型为bigint,而我这里引用表中的主键的类型为int。

4.解决方法:

找到当前的迁移文件
在这里插入图片描述

class Migration(migrations.Migration):

    dependencies = [
        ('goods', '0003_rename_default_image_url_sku_default_image'),
    ]

    operations = [
        migrations.CreateModel(
            name='GoodsVisitCount',
            fields=[
                ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
                ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
                ('id', models.AutoField(primary_key=True, serialize=False, unique=True, verbose_name='主键')),
                ('count', models.IntegerField(default=0, verbose_name='访问量')),
                ('date', models.DateField(auto_now_add=True, verbose_name='统计日期')),
                ('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='goods.goodscategory', verbose_name='商品分类')),
            ],
            options={
                'verbose_name': '统计分类商品访问量',
                'verbose_name_plural': '统计分类商品访问量',
                'db_table': 'tb_goods_visit',
            },
        ),
    ]

这里是通过migrations.CreateModel方法创建表,而django通过models.ForeignKey()创建外键,默认的类型为bigint,删除当前迁移文件migrations.CreateModel()方法的代码,改为通过migrations.runsql方法的sql语句的形式创建表,如下:

class Migration(migrations.Migration):

    dependencies = [
        ('goods', '0003_rename_default_image_url_sku_default_image'),
    ]

    operations = [

        migrations.RunSQL(
            """
            CREATE TABLE tb_goods_visit(
            create_time datetime(6) NOT NULL,
            update_time datetime(6) NOT NULL, 
            id integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
            count integer NOT NULL, 
            date date NOT NULL, 
            category_id int NOT NULL,
            CONSTRAINT tb_goods_visit_category_id_b3e36237_fk_tb_goods_category_id FOREIGN KEY(category_id) REFERENCES tb_goods_category(id)
             );
            """
    )
    ]

执行python manage.py migrate 命令

(meiduo_project_venv) F:\pychrom_python\web\django\meiduo_project\meiduo>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, areas, auth, contents, contenttypes, goods, oauth, sessions, users
Running migrations:
  Applying goods.0004_goodsvisitcount... OK

5.测试:

>>>(meiduo_project_venv) F:\pychrom_python\web\django\meiduo_project\meiduo>python manage.py shell
>>> from goods.models import GoodsVisitCount
>>> a=GoodsVisitCount.objects.get(id=1)
>>> a.category
<GoodsCategory: 相机>
>>> a.category.name
'相机'


成功关联表查询出记录

**

方法二:

**
通过更改配置文件下的DEFAULT_AUTO_FIELD配置

在这里插入图片描述
对于我上面的出现的问题,可以删除子应用下对应的迁移文件,删除数据库迁移表中对应的迁移记录,重新生成迁

移文件,重新迁移表到数据库即可,并且配置更改为:DEFAULT_AUTO_FIELD=django.db.models.IntegerField

相关更多说明可以查看https://docs.djangoproject.com/zh-hans/4.0/ref/settings/django官方文档中DEFAULT_AUTO_FIELD的配置说明。

到此結束,感謝閲讀~~~~~~~~~~~~~
小白自学,各路神仙勿喷

(Foreign key)是关系数据库中一个重要的概念,用于建立和加强两个表数据之间的连接,具有以下性质: - **关联性**:用于建立表与表之间的关联关系,一个表中的字段引用另一个表中的主字段,从而在两个表之间创建一种父子关系。例如,在学生表(stu)和班级表(class)之间,学生表中的`class_id`字段可以作为引用班级表中的`id`字段,建立学生和班级之间的关联 [^2]。 - **参照完整性**:约束确保了数据的参照完整性,即字段的值必须是其所引用的主字段中已存在的值,或者为`NULL`。这保证了数据的一致性和准确性,防止出现孤立的记录 [^2]。 - **操作规则**:当对引用表(父表)中的主进行更新或删除操作,需要根据的操作规则来处理子表中的相关记录。常见的操作规则包括`CASCADE`(级联操作,当父表记录删除或更新,子表中相关记录也会相应删除或更新)、`SET NULL`(当父表记录删除或更新,子表中相关记录的字段设置为`NULL`)、`RESTRICT`(限制操作,允许删除或更新父表中存在子表关联记录的主)等。例如,在Django模型中,`ForeignKey`的`on_delete=models.CASCADE`表示当关联的父表数据删除,当前表关联数据也会被删除 [^1]。 - **可空性**:字段可以被定义为允许为空(`NULL`),这意味着该字段可以引用任何父表记录。在定义,可以通过设置`null=True`来允许字段为空 [^1]。 - **反向操作**:在一些数据库框架(如Django)中,可以定义反向操作字段,用于从父表对象访问子表对象。例如,`ForeignKey`的`related_name`属性用于表示从相关对象到此对象的关系的名称,`related_query_name`属性用于反向操作连接前缀,如果`related_query_name`字段没有被赋值的话,那么`related_query_name`则会默认使用`related_name`这个值 [^1][^4]。 ### 示例代码 在SQL中创建包含的表: ```sql -- 创建班级表 CREATE TABLE class ( id INT PRIMARY KEY, class_name VARCHAR(50) ); -- 创建学生表,并设置 CREATE TABLE stu ( id INT PRIMARY KEY, student_name VARCHAR(50), class_id INT, FOREIGN KEY (class_id) REFERENCES class(id) ); ``` 在Django模型中定义: ```python from django.db import models class Project(models.Model): name = models.CharField(max_length=100) class Task(models.Model): project = models.ForeignKey(to=Project, on_delete=models.CASCADE, null=True, blank=True, related_name="tasks", related_query_name="task") task_name = models.CharField(max_length=100) ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值