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与PHP的实现版(推荐)
May 11 Python
Python+selenium实现自动循环扔QQ邮箱漂流瓶
May 29 Python
使用python语言,比较两个字符串是否相同的实例
Jun 29 Python
python3 实现验证码图片切割的方法
Dec 07 Python
Python缓存技术实现过程详解
Sep 25 Python
python 中值滤波,椒盐去噪,图片增强实例
Dec 18 Python
python内置模块collections知识点总结
Dec 19 Python
python访问hdfs的操作
Jun 06 Python
python中delattr删除对象方法的代码分析
Dec 15 Python
python爬虫基础之urllib的使用
Dec 31 Python
在Ubuntu中安装并配置Pycharm教程的实现方法
Jan 06 Python
如何正确理解python装饰器
Jun 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
for循环连续求和、九九乘法表代码
2012/02/20 PHP
基于MySQL到MongoDB简易对照表的详解
2013/06/03 PHP
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
2014/04/08 PHP
PHP中strnatcmp()函数“自然排序算法”进行字符串比较用法分析(对比strcmp函数)
2016/01/07 PHP
PHP基于双向链表与排序操作实现的会员排名功能示例
2017/12/26 PHP
关于jQuery参考实例 1.0 jQuery的哲学
2013/04/07 Javascript
animate动画示例(泪奔的小孩)及stop和delay的使用
2013/05/06 Javascript
Javascript倒计时页面跳转实例小结
2013/09/11 Javascript
jQuery自动完成插件completer附源码下载
2016/01/04 Javascript
全面解析Bootstrap中tab(选项卡)的使用方法
2016/06/06 Javascript
Javascript实现前端简单的路由实例
2016/09/11 Javascript
Bootstrap modal使用及点击外部不消失的解决方法
2016/12/13 Javascript
jQuery实现给input绑定回车事件的方法
2017/02/09 Javascript
搭建简单的nodejs http服务器详解
2017/03/09 NodeJs
初探JavaScript 面向对象(推荐)
2017/09/03 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
2019/03/19 Javascript
微信小程序template模板与component组件的区别和使用详解
2019/05/22 Javascript
微信小程序与公众号卡券/会员打通的问题
2019/07/25 Javascript
vuex vue简单使用知识点总结
2019/08/29 Javascript
python异步任务队列示例
2014/04/01 Python
python 远程统计文件代码分享
2015/05/14 Python
PyCharm代码提示忽略大小写设置方法
2018/10/28 Python
python实现多层感知器
2019/01/18 Python
python实现画循环圆
2019/11/23 Python
用Python去除图像的黑色或白色背景实例
2019/12/12 Python
探秘TensorFlow 和 NumPy 的 Broadcasting 机制
2020/03/13 Python
在Python中字典按值排序的实现方法
2020/11/12 Python
linux面试题参考答案(11)
2012/05/01 面试题
大学在校生求职信范文
2013/11/21 职场文书
对标管理实施方案
2014/03/12 职场文书
物业管理专业求职信
2014/06/11 职场文书
学校后勤工作总结2015
2015/05/15 职场文书
2019暑假阅读倡议书
2019/06/24 职场文书
导游词之杭州岳王庙
2019/11/13 职场文书
戴尔Win11系统no bootable devices found解决教程
2022/09/23 数码科技