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网络编程之TCP与UDP协议套接字用法示例
Feb 02 Python
python实现批量图片格式转换
Jun 16 Python
关于不懂Chromedriver如何配置环境变量问题解决方法
Jun 12 Python
python调用c++返回带成员指针的类指针实例
Dec 12 Python
Python实现AI自动抠图实例解析
Mar 05 Python
Python-jenkins 获取job构建信息方式
May 12 Python
python实现数字炸弹游戏
Jul 17 Python
python ssh 执行shell命令的示例
Sep 29 Python
Python基于tkinter canvas实现图片裁剪功能
Nov 05 Python
Python 排序最长英文单词链(列表中前一个单词末字母是下一个单词的首字母)
Dec 14 Python
python中最小二乘法详细讲解
Feb 19 Python
 分享一个Python 遇到数据库超好用的模块
Apr 06 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利用超级全局变量$_GET来接收表单数据的实例
2016/11/05 PHP
php实现的http请求封装示例
2016/11/08 PHP
PHP实现活动人选抽奖功能
2017/04/19 PHP
JavaScript基本对象
2007/01/11 Javascript
jQuery 学习 几种常用方法
2009/06/11 Javascript
JS操作iframe里的dom(实例讲解)
2014/01/29 Javascript
使用jQuery不判断浏览器高度解决iframe自适应高度问题
2014/12/16 Javascript
jquery实现两个图片渐变切换效果的方法
2015/06/25 Javascript
js重写方法的简单实现
2016/07/10 Javascript
基于Vue2的移动端开发环境搭建详解
2016/11/03 Javascript
JS简单实现数组去重的方法分析
2017/10/14 Javascript
angularjs实现柱状图动态加载的示例
2017/12/11 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
Layui实现主窗口和Iframe层参数传递
2019/11/14 Javascript
vue中选中多个选项并且改变选中的样式的实例代码
2020/09/16 Javascript
python处理json数据中的中文
2014/03/06 Python
python爬虫入门教程之点点美女图片爬虫代码分享
2014/09/02 Python
Python中if __name__ == "__main__"详细解释
2014/10/21 Python
python通过socket查询whois的方法
2015/07/18 Python
python编程实现归并排序
2017/04/14 Python
Python算法之求n个节点不同二叉树个数
2017/10/27 Python
Python测试模块doctest使用解析
2019/08/10 Python
Python imutils 填充图片周边为黑色的实现
2020/01/19 Python
canvas绘制表情包的示例代码
2018/07/09 HTML / CSS
斯凯奇新西兰官网:SKECHERS新西兰
2018/02/22 全球购物
医院总经理职责
2013/12/26 职场文书
早读迟到检讨书
2014/01/24 职场文书
幼儿教师师德演讲稿
2014/05/06 职场文书
大学生个人求职信
2014/06/02 职场文书
小学校园文化建设汇报材料
2014/08/19 职场文书
干部个人对照检查材料
2014/08/25 职场文书
事业单位考察材料范文
2014/12/25 职场文书
2016元旦主持人开场白
2015/12/03 职场文书
python 实现两个变量值进行交换的n种操作
2021/06/02 Python
Python中的datetime包与time包包和模块详情
2022/02/28 Python
UNION CREATIVE《Re:从零开始的异世界生活》雷姆手办
2022/03/20 日漫