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转码问题的解决方法
Oct 07 Python
Python实现批量下载文件
May 17 Python
python中管道用法入门实例
Jun 04 Python
python装饰器初探(推荐)
Jul 21 Python
python模块之time模块(实例讲解)
Sep 13 Python
Python获取CPU、内存使用率以及网络使用状态代码
Feb 08 Python
python dataframe常见操作方法:实现取行、列、切片、统计特征值
Jun 09 Python
pandas 条件搜索返回列表的方法
Oct 30 Python
python 不同方式读取文件速度不同的实例
Nov 09 Python
在Python中构建增广矩阵的实现方法
Jul 01 Python
Pandas DataFrame中的tuple元素遍历的实现
Oct 23 Python
python列表删除和多重循环退出原理详解
Mar 26 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的autoLoad自动加载机制
2012/09/27 PHP
PHP采用超长(超大)数字运算防止数字以科学计数法显示的方法
2016/04/01 PHP
php字符串操作常见问题小结
2016/10/11 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
Add a Formatted Table to a Word Document
2007/06/15 Javascript
jquery关于图形报表的运用实现代码
2011/01/06 Javascript
JavaScript高级程序设计(第3版)学习笔记5 js语句
2012/10/11 Javascript
使用node.js 获取客户端信息代码分享
2014/11/26 Javascript
JQuery选中checkbox方法代码实例(全选、反选、全不选)
2015/04/27 Javascript
javascript中clipboardData对象用法详解
2015/05/13 Javascript
JavaScript String(字符串)对象的简单实例(推荐)
2016/08/31 Javascript
layui radio性别单选框赋值方法
2018/08/15 Javascript
swiper.js插件实现pc端文本上下滑动功能示例
2018/12/03 Javascript
非常漂亮的js烟花效果
2020/03/10 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
原生jQuery实现只显示年份下拉框
2020/12/24 jQuery
[01:36]DOTA2完美大师赛趣味视频之与队友相处的十万个技巧
2017/11/19 DOTA
[10:42]Team Liquid Vs Newbee
2018/06/07 DOTA
跟老齐学Python之使用Python查询更新数据库
2014/11/25 Python
Django数据库操作的实例(增删改查)
2017/09/04 Python
keras.layer.input()用法说明
2020/06/16 Python
Python如何合并多个字典或映射
2020/07/24 Python
html5默认气泡修改的代码详解
2020/03/13 HTML / CSS
HTML5跳转小程序wx-open-launch-weapp的示例代码
2020/07/16 HTML / CSS
德国骆驼商店:ActiveFashionWorld
2017/11/18 全球购物
全球度假村:Club Med
2017/11/27 全球购物
小学教师自我鉴定
2013/11/07 职场文书
项目管理计划书
2014/01/09 职场文书
高中校园广播稿
2014/01/11 职场文书
教师师德演讲稿
2014/05/06 职场文书
新教师岗前培训方案
2014/06/05 职场文书
投标售后服务承诺书
2015/04/29 职场文书
高考百日冲刺决心书
2015/09/23 职场文书
高中班主任寄语
2019/06/21 职场文书
修改MySQL的默认密码的四种小方法
2021/05/26 MySQL
Python中npy和mat文件的保存与读取
2022/04/24 Python