关于Django外键赋值问题详解
时间:2019-03-31
本文章向大家介绍关于Django外键赋值问题详解,主要包括关于Django外键赋值问题详解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文主要给大家介绍关于Django外键赋值的相关内容,分享出来供大家参考学习,在开始之前,我们先来看一段代码:
class Article(models.Model): title = models.CharField(max_length=1024, default='') ... def __str__(self): return 'Article pk:%d %s' % (self.pk, self.title[:30]) class ArticleContent(models.Model): article = cached_fields.OneToOneField(Article) ...
写代码的的时候,发现了一个很奇怪的现象,当我给一个instance的外键(以_id结尾)赋值(数字)的时候 ,这个外键对应的instance的值并不会改变。
In [44]: ac = ArticleContent.objects.get(article_id=14269) In [45]: ac.article_id Out[45]: 14269 In [46]: ac.article_id = 14266 In [47]: ac.save() In [48]: ac.article Out[48]: <Article: Article pk:14266 EC: Russia, Ukraine to Meet in> In [49]: ac.article.pk Out[49]: 14266
如上面的代码所示,为了找到答案,我翻了一下Django的源码:
django/db/models/fields/related_descriptors.py def __get__(self, instance, cls=None): """ Get the related instance through the forward relation. With the example above, when getting ``child.parent``: - ``self`` is the descriptor managing the ``parent`` attribute - ``instance`` is the ``child`` instance - ``cls`` is the ``Child`` class (we don't need it) """ if instance is None: return self # The related instance is loaded from the database and then cached in # the attribute defined in self.cache_name. It can also be pre-cached # by the reverse accessor (ReverseOneToOneDescriptor). try: rel_obj = getattr(instance, self.cache_name) except AttributeError: val = self.field.get_local_related_value(instance) if None in val: rel_obj = None else: qs = self.get_queryset(instance=instance) qs = qs.filter(self.field.get_reverse_related_filter(instance)) # Assuming the database enforces foreign keys, this won't fail. rel_obj = qs.get() # If this is a one-to-one relation, set the reverse accessor # cache on the related object to the current instance to avoid # an extra SQL query if it's accessed later on. if not self.field.remote_field.multiple: setattr(rel_obj, self.field.remote_field.get_cache_name(), instance) setattr(instance, self.cache_name, rel_obj) if rel_obj is None and not self.field.null: raise self.RelatedObjectDoesNotExist( "%s has no %s." % (self.field.model.__name__, self.field.name) ) else: return rel_obj
注释得非常到位,当我们请求ac.article
的时候,会先去检查对应的cache(在这里是_article_cache
,感兴趣可以去看cache_name
的生成规则,就是外键名前面加下划线,后面加cache)存不存在,如果不存在那么就进行数据库请求,请求完之后会保存到cache中。
我们再看看__set__
,代码太长就不贴了(就在__get__
方法下面)。除了给外键字段(article
)赋值外,还会将pk字段(article_id
,是lh_field.attname
的值)设置为None,这样下次请求的时候就能拿到正确的值。
以上都是ForeignKey的Magic,而当我们给article_id
赋值的时候,只是在给一个普通的attribute赋值而已,没有任何magic,不会清理对应外键的cache,这时候拿到的instance仍然是cache中原来的那个instance。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
- spring cloud 学习(7) - 生产环境如何不停机热发布?
- jupyter notebook 在mac OS上的安装
- Hadoop(七)HDFS容错机制详解
- java一些常用并发工具示例
- 机器人来“抢工作”了,瑞典人为何能淡定处之
- 线性代数01 线性的大脑
- spring cloud 学习(10) - 利用springfox集成swagger
- Hadoop(六)之HDFS的存储原理(运行原理)
- Blockchain Global CEO Sam Lee:以大数据为基础,区块链技术加快决策生成速度
- Hadoop(五)搭建Hadoop客户端与Java访问HDFS集群
- 被解放的姜戈08 远走高飞
- mxnet安装及NDArray初体验
- MySQL(十五)之数据备份中mysqldump详解
- 安卓第十夜 亚当的诞生
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- sentinel的实际应用
- SpringMVC异常的处理机制
- 刷面试题的正确姿势!Android400道面试题+通关知识宝典助你进大厂,查漏补缺
- 3分钟短文:Laravel路由加模型等于?
- TSF微服务无法查看JVM监控问题
- Mitmproxy 的安装与使用案例
- leetcode之Bigram分词
- TensorFlow2 开发指南 | 01 手写数字识别快速入门
- Spring 数据初始 H2 后进行数据查询提示 Schema not found 错误
- Discourse CentOS 8 全新安装手册
- H2 数据库插入时间的方法
- Spring 配置的 H2 控制台 frameOptions 导致无法访问
- Spring Boot 和 Hibernate 的 H2 数据库配置来进行启动测试
- Java时间处理-LocalDateTime简介
- iOS音视频接入 - TRTC iOS端真机日志导出