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随手笔记第一篇(2)之初识列表和元组
Jan 23 Python
python编程实现归并排序
Apr 14 Python
彻底理解Python list切片原理
Oct 27 Python
django数据库migrate失败的解决方法解析
Feb 08 Python
Django的用户模块与权限系统的示例代码
Jul 24 Python
python selenium实现发送带附件的邮件代码实例
Dec 10 Python
termux中matplotlib无法显示中文问题的解决方法
Jan 11 Python
python 三种方法提取pdf中的图片
Feb 07 Python
浅谈Python协程asyncio
Jun 20 Python
总结几个非常实用的Python库
Jun 26 Python
pandas数值排序的实现实例
Jul 25 Python
python 远程执行命令的详细代码
Feb 15 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
php解决和避免form表单重复提交的几种方法
2016/08/31 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
JavaScript脚本性能的优化方法
2007/02/02 Javascript
jquery.alert 弹出式复选框实现代码
2009/06/15 Javascript
仅IE支持clearAttributes/mergeAttributes方法使用介绍
2012/05/04 Javascript
js检查页面上有无重复id的实现代码
2013/07/17 Javascript
JQuery判断checkbox是否选中及其它复选框操作方法合集
2015/06/01 Javascript
js随机生成字母数字组合的字符串 随机动画数字
2015/09/02 Javascript
jQueryUI DatePicker 添加时分秒
2016/06/04 Javascript
JS实现unicode和UTF-8之间的互相转换互转
2017/07/05 Javascript
详解HTML5 使用video标签实现选择摄像头功能
2017/10/25 Javascript
CentOS环境中MySQL修改root密码方法
2018/01/07 Javascript
Vue实现todolist删除功能
2018/06/26 Javascript
微信小程序踩坑记录之解决tabBar.list[3].selectedIconPath大小超过40kb
2018/07/04 Javascript
JS highcharts动态柱状图原理及实现
2020/10/16 Javascript
详解Python中的各种函数的使用
2015/05/24 Python
python爬虫的工作原理
2017/03/05 Python
浅谈使用Python变量时要避免的3个错误
2017/10/30 Python
Python实现的随机森林算法与简单总结
2018/01/30 Python
python画折线图的程序
2018/07/26 Python
django 将model转换为字典的方法示例
2018/10/16 Python
python3+selenium实现126邮箱登陆并发送邮件功能
2019/01/23 Python
python numpy存取文件的方式
2020/04/01 Python
keras 使用Lambda 快速新建层 添加多个参数操作
2020/06/10 Python
Pytorch损失函数nn.NLLLoss2d()用法说明
2020/07/07 Python
HTML5页面嵌入小程序没有返回按钮及返回页面空白的问题
2020/05/28 HTML / CSS
GUESS盖尔斯法国官网:美国时尚品牌
2016/09/23 全球购物
JBL澳大利亚官方商店:扬声器、耳机和音响系统
2018/05/24 全球购物
罗马尼亚在线杂货店:Pilulka.ro
2019/09/28 全球购物
工作证明范本(2篇)
2014/09/14 职场文书
2014教师党员自我评议总结
2014/09/19 职场文书
2014党员干部四风问题对照检查材料思想汇报
2014/09/24 职场文书
2015驻村干部工作总结
2015/04/07 职场文书
二十年同学聚会感言
2015/07/30 职场文书
公司安全管理制度范本
2015/08/05 职场文书
解析MySQL索引的作用
2022/03/03 MySQL