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 相关文章推荐
Flask入门教程实例:搭建一个静态博客
Mar 27 Python
利用Python脚本在Nginx和uwsgi上部署MoinMoin的教程
May 05 Python
实用自动化运维Python脚本分享
Jun 04 Python
解决python打不开文件(文件不存在)的问题
Feb 18 Python
Python参数解析模块sys、getopt、argparse使用与对比分析
Apr 02 Python
Django接收post前端返回的json格式数据代码实现
Jul 31 Python
python递归下载文件夹下所有文件
Aug 31 Python
python树的同构学习笔记
Sep 14 Python
将keras的h5模型转换为tensorflow的pb模型操作
May 25 Python
Python如何给函数库增加日志功能
Aug 04 Python
利用python 读写csv文件
Sep 10 Python
windows+vscode安装paddleOCR运行环境的步骤
Nov 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
修改了一个很不错的php验证码(支持中文)
2007/02/14 PHP
php Sql Server连接失败问题及解决办法
2009/08/07 PHP
解析array splice的移除数组中指定键的值,返回一个新的数组
2013/07/02 PHP
php获得用户ip地址的比较不错的方法
2014/02/08 PHP
php中单个数据库字段多列显示(单字段分页、横向输出)
2014/07/28 PHP
PHP引用的调用方法分析
2016/04/25 PHP
今天你说520了吗?不仅有php表白书还有java表白神器
2016/05/20 PHP
php求今天、昨天、明天时间戳的简单实现方法
2016/07/28 PHP
一句话JavaScript表单验证代码
2009/08/02 Javascript
调用js时ie6和ie7,ff的区别
2009/08/19 Javascript
jQuery实现id模糊查询的小例子
2013/03/19 Javascript
JS在textarea光标处插入文本的小例子
2013/03/22 Javascript
javascript实现日期三级联动下拉框选择菜单
2020/12/03 Javascript
bootstrap table表格使用方法详解
2017/04/26 Javascript
微信小程序页面跳转功能之从列表的item项跳转到下一个页面的方法
2017/11/27 Javascript
vue指令只能输入正数并且只能输入一个小数点的方法
2018/06/08 Javascript
微信小程序实现首页弹出广告
2020/12/03 Javascript
[42:34]VP vs VG 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
windows下python模拟鼠标点击和键盘输示例
2014/02/28 Python
python实现文本界面网络聊天室
2018/12/12 Python
Python实现的排列组合、破解密码算法示例
2019/04/12 Python
Python创建或生成列表的操作方法
2019/06/19 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
django正续或者倒序查库实例
2020/05/19 Python
Python 必须了解的5种高级特征
2020/09/10 Python
美国香薰蜡烛品牌:PADDYWAX
2018/10/06 全球购物
世界排名第一的万圣节服装店:Spirit Halloween
2018/10/16 全球购物
澳大利亚体育和露营装备在线/实体零售商:Find Sports
2020/06/03 全球购物
青年文明号复核材料
2014/02/11 职场文书
校园演讲稿汇总
2014/05/21 职场文书
企业诚信承诺书
2014/05/23 职场文书
家庭贫困证明书(3篇)
2014/09/15 职场文书
国际政治学专业推荐信
2014/09/26 职场文书
Python机器学习之逻辑回归
2021/05/11 Python
js Proxy的原理详解
2021/05/25 Javascript
深入理解mysql事务隔离级别和存储引擎
2022/04/12 MySQL