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中字符串和数字拼接报错的方法
Oct 23 Python
python使用__slots__让你的代码更加节省内存
Sep 05 Python
padas 生成excel 增加sheet表的实例
Dec 11 Python
使用Django连接Mysql数据库步骤
Jan 15 Python
用pyqt5 给按钮设置图标和css样式的方法
Jun 24 Python
如何用Python来搭建一个简单的推荐系统
Aug 07 Python
解决Django连接db遇到的问题
Aug 29 Python
python列表推导式操作解析
Nov 26 Python
python实现图像拼接功能
Mar 23 Python
django API 中接口的互相调用实例
Apr 01 Python
2021年的Python 时间轴和即将推出的功能详解
Jul 27 Python
python 调用js的四种方式
Apr 11 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
global.php
2006/12/09 PHP
php学习笔记 [预定义数组(超全局数组)]
2011/06/09 PHP
PHPExcel读取Excel文件的实现代码
2011/12/06 PHP
php.ini修改php上传文件大小限制的方法详解
2013/06/17 PHP
PHP Hash算法:Times33算法代码实例
2015/05/13 PHP
JS 强制设为首页的代码
2009/01/31 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
2010/12/06 Javascript
JavaScript基本编码模式小结
2012/05/23 Javascript
二叉树先序遍历的非递归算法具体实现
2014/01/09 Javascript
input点击后placeholder中的提示消息消失
2016/01/15 Javascript
微信小程序 触控事件详细介绍
2016/10/17 Javascript
localStorage实现便签小程序
2016/11/28 Javascript
ES6通过babel转码使用webpack使用import关键字
2016/12/13 Javascript
浅谈JsonObject中的key-value数据解析排序问题
2017/12/06 Javascript
把vue-router和express项目部署到服务器的方法
2018/02/21 Javascript
vue2.0在没有dev-server.js下的本地数据配置方法
2018/02/23 Javascript
详解在Vue中使用TypeScript的一些思考(实践)
2018/07/06 Javascript
前端防止用户重复提交js实现代码示例
2018/09/07 Javascript
如何使用JavaScript实现栈与队列
2019/06/24 Javascript
python分割文件的常用方法
2014/11/01 Python
Python函数式编程
2017/07/20 Python
Python3使用Matplotlib 绘制精美的数学函数图形
2019/04/11 Python
python f-string式格式化听语音流程讲解
2019/06/18 Python
python字符串替换re.sub()方法解析
2019/09/18 Python
python实现宿舍管理系统
2019/11/22 Python
详解字符串在Python内部是如何省内存的
2020/02/03 Python
使用python求解二次规划的问题
2020/02/29 Python
Python 生成短8位唯一id实战教程
2021/01/13 Python
浅析CSS3中鲜为人知的属性:-webkit-tap-highlight-color
2017/01/12 HTML / CSS
使用html5制作loading图的示例
2014/04/14 HTML / CSS
领先的钻石和订婚戒指零售商:Diamonds-USA
2016/12/11 全球购物
迎八一活动主题
2014/01/31 职场文书
园林技术专业求职信
2014/07/28 职场文书
党员民主评议个人总结
2014/10/20 职场文书
迎客户欢迎词三篇
2019/09/27 职场文书
win10系统计算机图标怎么调出来?win10调出计算机图标的方法
2022/08/14 数码科技