关于Django外键赋值问题详解


Posted in Python onAugust 13, 2017

本文主要给大家介绍关于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。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python使用cookie库操保存cookie详解
Mar 03 Python
django自定义Field实现一个字段存储以逗号分隔的字符串
Apr 27 Python
利用Python获取赶集网招聘信息前篇
Apr 18 Python
Python的Django中将文件上传至七牛云存储的代码分享
Jun 03 Python
Python实现自动添加脚本头信息的示例代码
Sep 02 Python
python中os和sys模块的区别与常用方法总结
Nov 14 Python
Python爬取数据保存为Json格式的代码示例
Apr 09 Python
python二维码操作:对QRCode和MyQR入门详解
Jun 24 Python
pycharm 2019 最新激活方式(pycharm破解、激活)
Sep 22 Python
pycharm激活方法到2099年(激活流程)
Sep 22 Python
Flask处理Web表单的实现方法
Jan 31 Python
golang特有程序结构入门教程
Jun 02 Python
python爬虫实战之最简单的网页爬虫教程
Aug 13 #Python
详解python中executemany和序列的使用方法
Aug 12 #Python
mysql 之通过配置文件链接数据库
Aug 12 #Python
python+selenium开发环境搭建图文教程
Aug 11 #Python
Python实现的递归神经网络简单示例
Aug 11 #Python
Python调用系统底层API播放wav文件的方法
Aug 11 #Python
Django 导出 Excel 代码的实例详解
Aug 11 #Python
You might like
基于PHP读取csv文件内容的详解
2013/06/18 PHP
WordPress中重置文章循环的rewind_posts()函数讲解
2016/01/11 PHP
详解php中反射的应用
2016/03/15 PHP
将HTML自动转为JS代码
2006/06/26 Javascript
form中限制文本字节数js代码
2007/06/10 Javascript
Jquery 表单取值赋值的一些基本操作
2009/10/11 Javascript
js实现倒计时(距离结束还有)示例代码
2013/07/24 Javascript
jQuery 鼠标经过(hover)事件的延时处理示例
2014/04/14 Javascript
基于BootStrap Metronic开发框架经验小结【四】Bootstrap图标的提取和利用
2016/05/12 Javascript
Javascript基础_嵌入图像的简单实现
2016/06/14 Javascript
AngularJS基础 ng-disabled 指令详解及简单示例
2016/08/01 Javascript
详解微信小程序开发之——wx.showToast(OBJECT)的使用
2017/01/18 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
vue2.x select2 指令封装详解
2017/10/12 Javascript
jQuery实现的淡入淡出图片轮播效果示例
2018/08/29 jQuery
Nodejs在局域网配置https访问的实现方法
2020/10/17 NodeJs
Vue实现点击当前行变色
2020/12/14 Vue.js
Python常用正则表达式符号浅析
2014/08/13 Python
PyChar学习教程之自定义文件与代码模板详解
2017/07/17 Python
Python提取频域特征知识点浅析
2019/03/04 Python
python 对字典按照value进行排序的方法
2019/05/09 Python
Python使用__new__()方法为对象分配内存及返回对象的引用示例
2019/09/20 Python
Python3 io文本及原始流I/O工具用法详解
2020/03/23 Python
Django admin管理工具TabularInline类用法详解
2020/05/14 Python
python:HDF和CSV存储优劣对比分析
2020/06/08 Python
迪拜领先运动补剂零售品牌中文站:Sporter商城
2019/08/20 全球购物
模具专业推荐信
2013/10/30 职场文书
体育教育毕业生自荐信
2013/11/21 职场文书
工业自动化毕业生自荐信范文
2014/01/04 职场文书
《神奇的克隆》教学反思
2014/04/10 职场文书
2014年行政工作总结
2014/11/19 职场文书
家属慰问信
2015/02/14 职场文书
党员考试作弊检讨书1000字
2015/02/16 职场文书
用Python selenium实现淘宝抢单机器人
2021/06/18 Python
gateway网关接口请求的校验方式
2021/07/15 Java/Android
Vue OpenLayer 为地图绘制风场效果
2022/04/24 Vue.js