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基于Tkinter库实现简单文本编辑器实例
May 05 Python
Python使用poplib模块和smtplib模块收发电子邮件的教程
Jul 02 Python
使用 Python 实现微信公众号粉丝迁移流程
Jan 03 Python
Python 使用类写装饰器的小技巧
Sep 30 Python
Django forms组件的使用教程
Oct 08 Python
使用Python自动生成HTML的方法示例
Aug 06 Python
Python数据可视化实现正态分布(高斯分布)
Aug 21 Python
python使用QQ邮箱实现自动发送邮件
Jun 22 Python
使用Pytorch搭建模型的步骤
Nov 16 Python
Django如何重置migration的几种情景
Feb 24 Python
Python语言规范之Pylint的详细用法
Jun 24 Python
Python正则表达式中flags参数的实例详解
Apr 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
PHP分页显示制作详细讲解
2008/11/19 PHP
php小偷相关截取函数备忘
2010/11/28 PHP
php获取bing每日壁纸示例分享
2014/02/25 PHP
PHP提示Warning:phpinfo() has been disabled函数禁用的解决方法
2014/12/17 PHP
phalcon框架使用指南
2016/02/23 PHP
PHP排序算法之堆排序(Heap Sort)实例详解
2018/04/21 PHP
初学prototype,发个JS接受URL参数的代码
2006/09/25 Javascript
js RuntimeObject() 获取ie里面自定义函数或者属性的集合
2010/11/23 Javascript
javascript学习笔记(二十) 获得和设置元素的特性(属性)
2012/06/20 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
检测一个函数是否是JavaScript原生函数的小技巧
2015/03/13 Javascript
JavaScript实现表格快速变色效果代码
2015/08/19 Javascript
详解Jquery实现ready和bind事件
2016/04/14 Javascript
jQuery绑定事件-多种实现方式总结
2016/05/09 Javascript
JS随机打乱数组的方法小结
2016/06/22 Javascript
javascript中BOM基础知识总结
2017/02/14 Javascript
ES6中Array.includes()函数的用法
2017/09/20 Javascript
vue中watch和computed的区别与使用方法
2020/08/23 Javascript
javascript使用canvas实现饼状图效果
2020/09/08 Javascript
基于vue实现微博三方登录流程解析
2020/11/04 Javascript
使用Python的Twisted框架实现一个简单的服务器
2015/04/16 Python
使用Python生成随机密码的示例分享
2016/02/18 Python
Python时间的精准正则匹配方法分析
2017/08/17 Python
Python中pygal绘制雷达图代码分享
2017/12/07 Python
python and or用法详解
2019/06/26 Python
Python帮你微信头像任意添加装饰别再@微信官方了
2019/09/25 Python
sklearn+python:线性回归案例
2020/02/24 Python
Django 自定义404 500等错误页面的实现
2020/03/08 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
2020/05/15 Python
95%的面试官都会问到的50道Java线程题,附答案
2012/08/03 面试题
网络编辑求职信
2014/04/30 职场文书
镇人大副主席民主生活会对照检查材料思想汇报
2014/10/01 职场文书
应届毕业生自荐信
2015/03/04 职场文书
幼儿园端午节活动总结
2015/05/05 职场文书
舌尖上的中国观后感
2015/06/02 职场文书
Pytorch distributed 多卡并行载入模型操作
2021/06/05 Python