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 相关文章推荐
在树莓派2或树莓派B+上安装Python和OpenCV的教程
Mar 30 Python
Python实现批量下载文件
May 17 Python
用Python的Django框架来制作一个RSS阅读器
Jul 22 Python
Python如何import文件夹下的文件(实现方法)
Jan 24 Python
Python编程argparse入门浅析
Feb 07 Python
Python3之读取连接过的网络并定位的方法
Apr 22 Python
python操作excel的方法
Aug 16 Python
python如何读取bin文件并下发串口
Jul 05 Python
python匿名函数的使用方法解析
Oct 10 Python
python定时任务 sched模块用法实例
Nov 04 Python
在django admin详情表单显示中添加自定义控件的实现
Mar 11 Python
Python+Appium实现自动化测试的使用步骤
Mar 24 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 md5下16位和32位的实现代码
2008/04/09 PHP
php 文件上传代码(限制jpg文件)
2010/01/05 PHP
Laravel 5框架学习之路由、控制器和视图简介
2015/04/07 PHP
php实现的网页版剪刀石头布游戏示例
2016/11/25 PHP
PHP实现分布式memcache设置web集群session同步的方法
2018/04/10 PHP
初学Javascript的一些总结
2008/11/03 Javascript
Iframe 自适应高度并实时监控高度变化的js代码
2009/10/30 Javascript
nodejs中实现sleep功能实例
2015/03/24 NodeJs
jQuery获取浏览器类型和版本号的方法
2016/07/05 Javascript
基于canvas的二维码邀请函生成插件
2017/02/14 Javascript
node.js中grunt和gulp的区别详解
2017/07/17 Javascript
react-native中ListView组件点击跳转的方法示例
2017/09/30 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
vuejs实现折叠面板展开收缩动画效果
2018/09/06 Javascript
在vue 中使用 less的教程详解
2018/09/26 Javascript
python实现sublime3的less编译插件示例
2014/04/27 Python
web.py获取上传文件名的正确方法
2014/08/26 Python
Python smallseg分词用法实例分析
2015/05/28 Python
Python读取网页内容的方法
2015/07/30 Python
Python正则表达式如何进行字符串替换实例
2016/12/28 Python
Sanic框架Cookies操作示例
2018/07/17 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
2019/02/21 Python
PyCharm 配置远程python解释器和在本地修改服务器代码
2019/07/23 Python
python反转列表的三种方式解析
2019/11/08 Python
Python turtle库绘制菱形的3种方式小结
2019/11/23 Python
基于 HTML5 Canvas实现 的交互式地铁线路图
2018/03/05 HTML / CSS
HTML5实现可缩放时钟代码
2017/08/28 HTML / CSS
药学职务聘任书
2014/03/29 职场文书
竞聘演讲稿精彩开头和结尾
2014/05/14 职场文书
食品安全宣传标语
2014/06/07 职场文书
2015年医德医风工作总结
2015/04/02 职场文书
电台广播稿范文
2015/08/19 职场文书
会计主管竞聘书
2015/09/15 职场文书
详解前端任务构建利器Gulp.js使用指南
2021/04/30 Javascript
CSS控制继承中的height能变为可继承吗
2022/06/10 HTML / CSS
了解MySQL查询语句执行过程(5大组件)
2022/08/14 MySQL