Django ForeignKey与数据库的FOREIGN KEY约束详解
作者:唯美落叶 发布时间:2024-01-18 15:17:40
数据库在高并发的场景下使用外键约束会有锁问题并且使用外键会增加运维成本,所以很多公司都规定生产环境的数据库禁止使用外键。
那么不使用外键约束的情况下使用 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方法更新才能达到我的需求。
来源:https://blog.csdn.net/Focus_on_linux/article/details/90521503
猜你喜欢
- 本文实例讲述了Python读写ini文件的方法。分享给大家供大家参考。具体如下:比如有一个文件update.ini,里面有这些内容:[ZIP
- python实现12306余票查询我们说先在浏览器中打开开发者工具(F12),尝试一次余票的查询,通过开发者工具查看发出请求的包余票查询界面
- 阅读上一篇教程:WEB2.0网页制作标准教程(8)CSS布局入门接下来开始要真正设计布局了。和传统的方法一样,你首先要在脑海里有大致的轮廓构
- 第一步 : 从清华大学开源软件镜像站下载Anaconda:https://mirrors.tuna.tsinghua.edu.cn/anac
- Python画图(线条颜色、大小、线形)先放基础代码,下面讲述效果:import matplotlib.pyplot as pltimpor
- 在应用SA-FileUp时,必须确认用户已对目的路径有读、写、删除的权力。在多文件上传中,由于浏览器不支持SIZE= 属性,所以对多文件的情
- 学了几天正则,差不多该总结整理写成果了,之前就想写语法高亮匹配来着,不过水平不够,看着例子都不理解。那么我们来分析下两位大神 次碳酸钴 和
- 目录前言解决方案工具介绍工作原理使用限制使用注意使用示例部分参数说明输出结果示例腾讯云数据库 MySQL 使用注意总结一下前言写作案例分析,
- 高斯模糊的介绍与原理通常,图像处理软件会提供"模糊"(blur)滤镜,使图片产生模糊的效果。"模糊"
- 前言我们在开发应用是经常会需要用到一些数据的存储,存储的方式有多种,使用数据库是一种比较受大家欢迎的方式。但是对于一些小型的应用,如一些移动
- 亲测十分靠谱下面是解决该问题的方法第一步:关闭SIP系统保护1.重启系统时按住Command+R进入恢复模式(记住是你在重新启动时,不是启动
- 现在很流行springboot的开发,小编闲来无事也学了学,开发过程中遇见了log4j日志的一个小小问题,特此记载。首先在pox.xml中引
- 新建一个项目 app02在 app02/ 下创建 urls.py:from django.conf.urls import urlfrom
- Pycharm安装cv2 [python3.6]python解释器为Anaconda的3.6版本下载在这里选择对应的版本进行下载,其中参数分
- 本文实例讲述了Python 面向对象静态方法、类方法、属性方法知识点。分享给大家供大家参考,具体如下:(1)静态方法--》-@staticm
- 前言MySQL中有六种日志文件,分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(e
- 如下所示:python3:img_path = ' 'im = cv2.imdecode(np.fromfile
- 有关 Web 字体的话题正在增多,对 Web 设计师来说,他们并不关注技术细节,不管是 TrueType 的 Hinting 技术
- PyQt5布局控件QFormLayout简介QFormLayout是label-field式的表单布局,顾明思议,就是实现表单方式的布局,表
- Opencv-Python图像透视变换cv2.warpPerspective代码如下:# -*- coding:utf-8 -*-impor