Django ForeignKey与数据库的FOREIGN KEY约束详解


Posted in Python onMay 20, 2020

数据库在高并发的场景下使用外键约束会有锁问题并且使用外键会增加运维成本,所以很多公司都规定生产环境的数据库禁止使用外键。

那么不使用外键约束的情况下使用 Django ORM 如何实现关联查询两个表呢?这曾是困扰我很久的一个问题,今天终于找到了答案,写出来分享一下。

Django 的 ForeignKey 和数据库的 FOREIGN KEY 并不一样。Django 的 ForeignKey 是一种逻辑上的两个表的关联关系,可以指定是否使用数据库的 FOREIGN KEY 约束。

在开头提到的场景下,我们可以这样创建两个表对应的 Model,以省和市的关联举例:

# demo/models.py
from django.db import models

class Province(models.Model):
  name = models.CharField(max_length=16)

  def __unicode__(self):
    return self.name

class City(models.Model):
  name = models.CharField(max_length=16)
  province = models.ForeignKey(Province, null=True, on_delete=models.SET_NULL,
                 related_name='cities', db_constraint=False)
  def __unicode__(self):
    return self.name

以上的 models.py 在执行 migrate 时生成的 SQL 如下(MySQL数据库):

CREATE TABLE `demo_city` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(16) NOT NULL);
CREATE TABLE `demo_province` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(16) NOT NULL);
ALTER TABLE `demo_city` ADD COLUMN `province_id` integer NULL;
CREATE INDEX `demo_city_province_id_50fffd49` ON `demo_city` (`province_id`);

如果 ForeignKey 不添加db_constraint=False 参数,会在数据库中使用外键约束,生成以下SQL:

ALTER TABLE `demo_city` ADD CONSTRAINT `demo_city_province_id_aff53934_fk_key_province_id` FOREIGN KEY (`province_id`) REFERENCES `demo_province` (`id`);

另外,ForeignKey 的 on_delete 参数默认为 on_delete=models.CASCADE,表示使用数据库的级联删除,使用 on_delete=models.SET_NULL 可以使删除 Province 时将关联的 City 表对应的 province_id 值设为 NULL

使用这种方式不会破坏 Django 的反向关联查询,以下查询仍然会返回正确的结果:

Province.objects.filter(cities__name='xxx')

实际执行的 SQL 为一个 Inner Join 查询:

SELECT `demo_province`.`id`, `demo_province`.`name` FROM `demo_province` INNER JOIN `demo_city` ON (`demo_province`.`id` = `demo_city`.`province_id`) WHERE `demo_city`.`name` = xxx;

补充知识:关于Django模型中中定义auto_now=True 数据库中的时间并没有自动更新

django的orm关于更新数据库的方法有update和save两种方法。

前提在模型中设置了auto_now=True时间戳属性,为了方便数据库自动更新时间,而

使用update更新的记录,数据库中并没有自动更新,达到我的需求。

auto_now=True自动更新,有一个条件,就是要通过django的model层。

如create或是save方法。

如果是filter之后update方法,则直接调用的是sql,不会通过model层,

所以不会自动更新此时间。所以使用save方法更新才能达到我的需求。

以上这篇Django ForeignKey与数据库的FOREIGN KEY约束详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的__SLOTS__属性使用示例
Feb 18 Python
python获取文件扩展名的方法
Jul 06 Python
浅谈numpy数组的几种排序方式
Dec 15 Python
浅谈Python中range和xrange的区别
Dec 20 Python
python隐藏终端执行cmd命令的方法
Jun 24 Python
python实现字符串完美拆分split()的方法
Jul 16 Python
Python中的 ansible 动态Inventory 脚本
Jan 19 Python
python十进制转二进制的详解
Feb 07 Python
Python单例模式的四种创建方式实例解析
Mar 04 Python
Tensorflow中的dropout的使用方法
Mar 13 Python
python实现简单坦克大战
Mar 27 Python
使用 Python 读取电子表格中的数据实例详解
Apr 17 Python
让Django的BooleanField支持字符串形式的输入方式
May 20 #Python
django 解决model中类写不到数据库中,数据库无此字段的问题
May 20 #Python
基于Python脚本实现邮件报警功能
May 20 #Python
完美解决Django2.0中models下的ForeignKey()问题
May 19 #Python
Django 解决model 反向引用中的related_name问题
May 19 #Python
django queryset 去重 .distinct()说明
May 19 #Python
django正续或者倒序查库实例
May 19 #Python
You might like
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
巧用php中的array_filter()函数去掉多维空值的代码分享
2012/09/07 PHP
用Simple Excel导出xls实现方法
2012/12/06 PHP
8个必备的PHP功能实例代码
2013/10/27 PHP
PHP实现数组根据某个字段进行水平合并,横向合并案例分析
2019/10/08 PHP
PHP实现微信提现功能(微信商城)
2019/11/21 PHP
javascript 数组学习资料收集
2010/04/11 Javascript
jQuery EasyUI API 中文文档 - Form表单
2011/10/06 Javascript
javascript计算当月剩余天数(天数计算器)示例代码
2014/01/09 Javascript
JavaScript中双叹号!!作用示例介绍
2014/09/21 Javascript
前端性能优化及技巧
2016/05/06 Javascript
javascript之with的使用(阿里云、淘宝使用代码分析)
2016/10/11 Javascript
JS button按钮实现submit按钮提交效果
2016/11/01 Javascript
H5实现仿flash效果的实现代码
2017/09/29 Javascript
使用 Node.js 模拟滑动拼图验证码操作的示例代码
2017/11/02 Javascript
微信小程序实现image组件图片自适应宽度比例显示的方法
2018/01/16 Javascript
微信小程序实现手势图案锁屏功能
2018/01/30 Javascript
判断文字超过2行添加展开按钮,未超过则不显示,溢出部分显示省略号
2019/04/28 Javascript
vue实现配置全局访问路径头(axios)
2019/11/01 Javascript
Vue v-for循环之@click点击事件获取元素示例
2019/11/09 Javascript
解决Angularjs异步操作后台请求用$q.all排列先后顺序问题
2019/11/29 Javascript
JavaScript判断数据类型有几种方法及区别介绍
2020/09/02 Javascript
Bootstrap FileInput实现图片上传功能
2021/01/28 Javascript
python获取各操作系统硬件信息的方法
2015/06/03 Python
python画图——实现在图上标注上具体数值的方法
2019/07/08 Python
简单聊聊H5的pushState与replaceState的用法
2018/04/03 HTML / CSS
大学生应聘自荐信
2013/10/11 职场文书
最新党员思想汇报
2014/01/01 职场文书
《姥姥的剪纸》教学反思
2014/02/25 职场文书
应聘销售主管的求职信
2014/04/26 职场文书
酒店周年庆活动方案
2014/08/21 职场文书
面试复试通知单
2015/04/24 职场文书
六五普法先进个人主要事迹材料
2015/11/03 职场文书
解决numpy数组互换两行及赋值的问题
2021/04/17 Python
Python 如何解决稀疏矩阵运算
2021/05/26 Python
《废话连篇——致新手》——chinapizza
2022/04/05 无线电