【问题标题】:Setting GenericForeignKey field value in Django在 Django 中设置 GenericForeignKey 字段值
【发布时间】:2016-07-30 23:57:13
【问题描述】:

我最近一直在阅读有关泛型关系的文章。我知道GenericForeignKey 是使用ForeignKeyPositiveIntegerField 字段定义和管理通用关系。我潜入源代码寻找GenericForeignKey__set__ 方法,看看它是如何工作的。

这是GenericForeignKey.__set__() 的sn-p:

def __set__(self, instance, value):
    ct = None
    fk = None
    if value is not None:
        ct = self.get_content_type(obj=value)
        fk = value._get_pk_val()
    setattr(instance, self.ct_field, ct)
    setattr(instance, self.fk_field, fk)
    setattr(instance, self.cache_attr, value)

以及来自 django docs example 的模型定义:

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

问题:

当我将guido 的值分配给content_object 时,每个参数的值是多少:GenericForeignKey.__set__() 中的selfinstancevalue

self=<GenericForeignKey: 1>instance='content_object'value=<User: guido>

>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()

【问题讨论】:

标签: python django django-contenttypes


【解决方案1】:

__set__ 方法适用于descriptors

以下简单示例将显示传递给__set__ 的参数是什么:

class MyDescriptor:
    def __set__(self, instance, value):
        print((self, instance, value))

class MyClass:
    attr = MyDescriptor()

inst = MyClass()
inst.attr = "foo"

你会得到类似的东西:

<__main__.MyDescriptor object at 0x000002017192AD68>,   # self
<__main__.MyClass object at 0x000002017192ACF8>,        # instance
'foo'                                                   # value

具体来说:

  • selfMyDescriptor 描述符 (MyClass.attr) 的实例,
  • instanceMyClass 类 (inst) 的实例,并且
  • value 是您将属性设置为 ("foo")。

查看更详尽的示例here

因此,如果没有类似地深入研究 Django 代码,似乎:

  • selfGenericForeignKey 描述符 (TaggedItem.content_object) 的实例,
  • instanceTaggedItem 类的实例,并且
  • value 是您要设置的属性。

但请注意,使用这一行:

t = TaggedItem(content_object=guido, tag='bdfl')

看起来你正在创建一个TaggedItem,它创建这个行的描述符

content_object = GenericForeignKey('content_type', 'object_id')

因此,至少从您发布的代码来看,__set__ 方法不会被调用。而是调用GenericForeignKey__init__ 方法。

要调用GenericForeignKey__set__ 方法,您需要有一个具有GenericForeignKey 描述符作为属性的类的实例(称为inst)(称为attr ),然后写如下内容:

inst.attr = "not guido"

然后,GenericForeignKey 描述符的__set__ 方法将被调用

【讨论】:

  • 有道理!但是它没有明确回答问题,它为您提供了理解我所问问题的工具。
  • @an0o0nym 关于“当我将 guido 的值分配给 content_object 时,这些参数中的每一个的值是多少:GenericForeignKey.__set__() 中的 self、instance 和 value?”答案有点解决它。它会告诉你如果调用它的参数会是什么,但我解释了为什么它可能不会被调用。
猜你喜欢
  • 2017-08-20
  • 2014-08-19
  • 2011-08-20
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-29
相关资源
最近更新 更多