Django:使用真实对象设置通用(content_type)字段将其设置为None

int*_*tar 1 django django-models

更新3(首先阅读):

是的,这是由对象"配置文件"未保存引起的.对于那些得到相同症状的人来说,道德是"如果一个ForeignKey字段似乎在为它分配一个真实对象时被设置为无,那可能是因为其他对象尚未被保存."

即使您100%确定它已保存,再次检查;-)


嗨,

我在Django的类中使用content_type/generic外键.

创建类实例的行大致如下:

tag =  SecurityTag(name='name',agent=an_agent,resource=a_resource,interface=an_interface)
Run Code Online (Sandbox Code Playgroud)

代理和资源都是content_type字段.

大多数情况下,这可以按照我的预期工作并创建适当的对象.但我有一个特定的情况,我称这行为创建一个SecurityTag,但代理字段的值似乎最终为无.

现在,在这种特殊情况下,我在前一行中测试an_agent的值确实包含代理类型的现有的,已保存的Django.model对象.确实如此.

然而,生成的SecurityTag记录在此字段中显示为None.

我对此非常困惑.我猜这个沿线的某个地方,ORM尝试在an_agent中提取对象的id失败了,但是没有引发错误消息或异常.我已经检查过an_agent对象已保存并且在其id字段中有一个值.

有人见过这样的东西吗?还是有什么想法?

====

更新:10天后,在新环境中再次咬同样的错误:

这里有一些描述"安全标记"对象的代码,它基本上是一个映射

a)某种权限角色(在我们的系统中称为"代理"),它是一种通用的content_type,

b)资源,也是一个通用的content_type,(并且在当前的问题中给出了Pinax"Profile"),

和c)"接口"(基本上是一种访问类型......例如"可查看"或"可编辑",只是一个字符串)

class SecurityTag(models.Model) :
    name = models.CharField(max_length='50')
    agent_content_type = models.ForeignKey(ContentType,related_name='security_tag_agent')
    agent_object_id = models.PositiveIntegerField()
    agent = generic.GenericForeignKey('agent_content_type', 'agent_object_id')

    interface = models.CharField(max_length='50')

    resource_content_type = models.ForeignKey(ContentType,related_name='security_tag_resource')
    resource_object_id = models.PositiveIntegerField()
    resource = generic.GenericForeignKey('resource_content_type', 'resource_object_id')
Run Code Online (Sandbox Code Playgroud)

在特定时刻,我这样做:

print "before %s, %s" % (self.resource,self.agent)
t = SecurityTag(name=self.tag_name,agent=self.agent,resource=self.resource,interface=self.interface_id)
print "after %s, %s, %s, %s" % (t.resource,t.resource_content_type,type(t.resource),t.resource_object_id)
Run Code Online (Sandbox Code Playgroud)

其结果是之前,"资源"变量确实引用了一个配置文件,但之后......

before phil, TgGroup object
after None, profile, <type 'NoneType'>, None
Run Code Online (Sandbox Code Playgroud)

换句话说,虽然t.resource_content_type的值已设置为"profile",但其他所有内容均为None.在我之前遇到这个问题时,我通过重新加载我试图分配给泛型类型的东西来"解决"它.我开始怀疑这是否是某种ORM缓存问题...变量"self.resource"是否包含某种代理对象而不是真实的东西?

一种可能性是配置文件尚未保存.但是,此代码被称为配置文件的after_save信号的结果.(它正在设置默认权限),那么是否可能未提交配置文件保存或其他内容?

更新2:根据马修的建议,我补充道

print self.resource._get_pk_value() and self.resource.id
Run Code Online (Sandbox Code Playgroud)

已经爆炸说Profile没有_get_pk_value()

Mat*_*sen 5

所以这就是我注意到的通过Django代码:当你通过构造函数创建一个模型对象的新实例时,一个pre-init函数调用(通过信号)任何泛型对象引用.

它不是直接存储您传入的对象,而是存储类型和主键.

如果你的对象是持久化的并且有一个ID,那么这很好用,因为当你以后获得该字段时,它会从数据库中检索它.

但是 - 如果您的对象没有ID,则获取代码不返回任何内容,并且getter返回None!

您可以django.contrib.contenttypes.generic.GenericForeignKeyinstance_pre_init__get__函数中查看代码.