关于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原始套接字编程示例分享
Feb 21 Python
python处理二进制数据的方法
Jun 03 Python
Python使用pygame模块编写俄罗斯方块游戏的代码实例
Dec 08 Python
Python获取文件所在目录和文件名的方法
Jan 12 Python
R vs. Python 数据分析中谁与争锋?
Oct 18 Python
python计算日期之间的放假日期
Jun 05 Python
django框架使用方法详解
Jul 18 Python
python命名空间(namespace)简单介绍
Aug 10 Python
python matplotlib 画dataframe的时间序列图实例
Nov 20 Python
基于python爬取有道翻译过程图解
Mar 31 Python
python Socket网络编程实现C/S模式和P2P
Jun 22 Python
如何利用opencv判断两张图片是否相同详解
Jul 07 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第一季视频教程(李炎恢+php100 不断更新)
2011/05/29 PHP
PHP删除数组中空值的方法介绍
2014/04/14 PHP
php实现session自定义会话处理器的方法
2015/01/27 PHP
php传值方式和ajax的验证功能
2017/03/27 PHP
PHP区块查询实现方法分析
2018/05/12 PHP
许愿墙中用到的函数
2006/10/07 Javascript
JS 对象属性相关(检查属性、枚举属性等)
2015/04/05 Javascript
JavaScript实现文本框中默认显示背景图片在获得焦点后消失的方法
2015/07/01 Javascript
jQuery实现简单下拉导航效果
2015/09/07 Javascript
Angular发布1.5正式版,专注于向Angular 2的过渡
2016/02/18 Javascript
jQuery Mobile操作HTML5的常用函数总结
2016/05/17 Javascript
ES6新特性二:Iterator(遍历器)和for-of循环详解
2017/04/20 Javascript
微信小程序在ios下Echarts图表不能滑动的问题解决
2019/07/10 Javascript
ES6的异步操作之promise用法和async函数的具体使用
2019/12/06 Javascript
Vue实现星级评价效果实例详解
2019/12/30 Javascript
JS数组方法push()、pop()用法实例分析
2020/01/18 Javascript
JavaScript实现串行请求的示例代码
2020/09/14 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
2021/02/05 Javascript
Python中使用dom模块生成XML文件示例
2015/04/05 Python
Python使用MONGODB入门实例
2015/05/11 Python
Python实现根据IP地址和子网掩码算出网段的方法
2015/07/30 Python
Python的网络编程库Gevent的安装及使用技巧
2016/06/24 Python
Python3.4 tkinter,PIL图片转换
2018/06/21 Python
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
python使用MQTT给硬件传输图片的实现方法
2019/05/05 Python
python全栈知识点总结
2019/07/01 Python
Python实现制度转换(货币,温度,长度)
2019/07/14 Python
Python 实现集合Set的示例
2020/12/21 Python
伦敦平价潮流珠宝首饰品牌:Astrid & Miyu
2016/10/10 全球购物
佳能德国网上商店:Canon德国
2017/03/18 全球购物
毕业学生推荐信
2013/12/01 职场文书
人力资源管理专业自荐书范文
2014/02/10 职场文书
停电放假通知
2015/04/14 职场文书
2015年教师见习期工作总结
2015/05/20 职场文书
七年级生物教学反思
2016/02/20 职场文书
低门槛开发iOS、Android、小程序应用的前端框架详解
2021/10/16 Javascript