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学习数据结构实例代码
May 11 Python
探究Python中isalnum()方法的使用
May 18 Python
python实现二维码扫码自动登录淘宝
Dec 27 Python
python fabric实现远程部署
Jan 05 Python
微信跳一跳自动运行python脚本
Jan 08 Python
基于python实现简单日历
Jul 28 Python
在python 中实现运行多条shell命令
Jan 07 Python
python读写csv文件方法详细总结
Jul 05 Python
python中web框架的自定义创建
Sep 08 Python
Pandas中DataFrame基本函数整理(小结)
Jul 20 Python
Python列表嵌套常见坑点及解决方案
Sep 30 Python
Python读取图像并显示灰度图的实现
Dec 01 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
页面利用渐进式JPEG来提升用户体验度
2014/12/01 PHP
PHP使用递归方式列出当前目录下所有文件的方法
2015/06/02 PHP
php自定义分页类完整实例
2015/12/25 PHP
php用wangeditor3实现图片上传功能
2019/08/22 PHP
js下判断 iframe 是否加载完成的完美方法
2010/10/26 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
2013/02/26 Javascript
JS保留两位小数 四舍五入函数的小例子
2013/11/20 Javascript
jquery.post用法关于type设置问题补充
2014/01/03 Javascript
jQuery+CSS实现的网页二级下滑菜单效果
2015/08/25 Javascript
Express框架之connect-flash详解
2017/05/31 Javascript
JavaScript设计模式之工厂模式和抽象工厂模式定义与用法分析
2018/07/26 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
详解vue中使用微信jssdk
2019/04/19 Javascript
微信小程序登录态和检验注册过没的app.js写法
2019/05/22 Javascript
uni-app实现点赞评论功能
2019/11/25 Javascript
js实现AI五子棋人机大战
2020/05/28 Javascript
ES6 Object.assign()的用法及其使用
2020/01/18 Javascript
原生JavaScript实现随机点名表
2021/01/14 Javascript
Flask框架各种常见装饰器示例
2018/07/17 Python
Python WEB应用部署的实现方法
2019/01/02 Python
Python元组常见操作示例
2019/02/19 Python
python内存监控工具memory_profiler和guppy的用法详解
2019/07/29 Python
python 图像的离散傅立叶变换实例
2020/01/02 Python
Python PyInstaller安装和使用教程详解
2020/01/08 Python
Python类super()及私有属性原理解析
2020/06/15 Python
python中remove函数的踩坑记录
2021/01/04 Python
CSS3制作翻转效果_动力节点Java学院整理
2017/07/11 HTML / CSS
美国电子产品折扣网站:Daily Steals
2017/05/20 全球购物
英国第一的市场和亚马逊替代品:OnBuy
2019/03/16 全球购物
奥林匹亚体育:Olympia Sports
2020/12/30 全球购物
统计每一学生的平均成绩
2014/06/06 面试题
《梅花魂》教学反思
2014/04/30 职场文书
五好文明家庭事迹材料
2014/12/20 职场文书
护士工作心得体会
2016/01/25 职场文书
python引入其他文件夹下的py文件具体方法
2021/05/23 Python
欧元符号 €
2022/02/17 杂记