关于Django外键赋值问题详解

关于Django外键赋值问题详解,第1张

概述本文主要给大家介绍关于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_IDOut[45]: 14269In [46]: ac.article_ID = 14266In [47]: ac.save()In [48]: ac.articleOut[48]: <Article: Article pk:14266 EC: Russia,Ukraine to Meet in>In [49]: ac.article.pkOut[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。

总结

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

总结

以上是内存溢出为你收集整理的关于Django外键赋值问题详解全部内容,希望文章能够帮你解决关于Django外键赋值问题详解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1201778.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存