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生成随机mac地址的方法
Mar 16 Python
python实现中文转换url编码的方法
Jun 14 Python
Python实现读写sqlite3数据库并将统计数据写入Excel的方法示例
Aug 07 Python
详解Python requests 超时和重试的方法
Dec 18 Python
在Python 中同一个类两个函数间变量的调用方法
Jan 31 Python
使用python的pexpect模块,实现远程免密登录的示例
Feb 14 Python
int在python中的含义以及用法
Jun 27 Python
PYTHON如何读取和写入EXCEL里面的数据
Oct 28 Python
pytorch中图像的数据格式实例
Feb 11 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
Nov 27 Python
浅谈Python中的函数(def)及参数传递操作
May 25 Python
pytorch中的 .view()函数的用法介绍
Mar 17 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 IP转换整形(ip2long)的详解
2013/06/06 PHP
PHP实现图片裁剪、添加水印效果代码
2014/10/01 PHP
php防止sql注入简单分析
2015/03/18 PHP
PHP中使用socket方式GET、POST数据实例
2015/04/02 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
PHP实现的简单留言板功能示例【基于thinkPHP框架】
2018/12/07 PHP
javascript eval和JSON之间的联系
2009/12/31 Javascript
JQuery 将元素显示在屏幕的中央的代码
2010/02/27 Javascript
Jquery实现Div上下移动示例
2014/04/23 Javascript
Jquery Post处理后不进入回调的原因及解决方法
2014/07/15 Javascript
jquery单选框radio绑定click事件实现方法
2015/01/14 Javascript
Jquery实现鼠标移动放大图片功能实例
2015/03/25 Javascript
JQuery中ajax方法访问web服务实例
2015/07/18 Javascript
JavaScript与ActionScript3两者的同性与差异性
2016/09/22 Javascript
JavaScript实现url参数转成json形式
2016/09/25 Javascript
layui弹出层按钮提交iframe表单的方法
2018/08/20 Javascript
vue 监听键盘回车事件详解 @keyup.enter || @keyup.enter.native
2018/08/25 Javascript
vue跳转方式(打开新页面)及传参操作示例
2020/01/26 Javascript
vue 递归组件的简单使用示例
2021/01/14 Vue.js
[55:54]FNATIC vs EG 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python常用列表数据结构小结
2014/08/06 Python
详解在Python中处理异常的教程
2015/05/24 Python
Python向Excel中插入图片的简单实现方法
2018/04/24 Python
Python3爬虫爬取百姓网列表并保存为json功能示例【基于request、lxml和json模块】
2018/12/05 Python
使用python自动追踪你的快递(物流推送邮箱)
2020/03/17 Python
Scrapy项目实战之爬取某社区用户详情
2020/09/17 Python
经理秘书找工作求职信
2013/12/19 职场文书
工厂仓管员岗位职责
2014/01/01 职场文书
大学生职业生涯规划范文——找准自我,定位人生
2014/01/23 职场文书
师德学习感言
2014/01/31 职场文书
乡镇党的群众路线教育实践活动个人整改方案
2014/10/31 职场文书
皇城相府导游词
2015/02/06 职场文书
英语教师求职信范文
2015/03/20 职场文书
劳动仲裁撤诉申请书
2015/05/18 职场文书
Python读取文件夹下的所有文件实例代码
2021/04/02 Python
js前端设计模式优化50%表单校验代码示例
2022/06/21 Javascript