简体   繁体   English

从Django中的通用外键获取值

[英]Getting values from generic foreign key in Django

I have a model defined with a generic foreign key like this: 我有一个用通用外键定义的模型,如下所示:

class Status(models.Model):
    request_type = models.ForeignKey(ContentType)
    request_id = models.PositiveIntegerField()
    request = GenericForeignKey('request_type', 'request_id')

When I grab the relations with a normal queryset it works fine. 当我使用普通查询集获取关系时,它可以正常工作。

statuses = Status.objects.all()
for status in statuses:
    print status.request.name

This prints all the names normally. 这将正常打印所有名称。

However I am using Django eztables which relies on grabbing the values like 但是我正在使用Django eztables,它依赖于获取像

statuses = Status.objects.all().values('request__name')

However when I try this I get: 但是,当我尝试这样做时,我得到:

FieldError: Cannot resolve keyword 'request' into field. Choices are: request_id, request_type, request_type_id

Is there a way to achieve this in Django? 有没有一种方法可以在Django中实现?

I figured it out. 我想到了。

You must define your object with names like this: 您必须使用以下名称定义对象:

class Status(BaseRequestStatus):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    ... more data

Then in the object you would like to filter on you must create a reverse generic relationship: 然后,在要过滤的对象中,必须创建反向通用关系:

class Request(models.Model):
    statuses = GenericRelation(Status, related_query_name='request')
    ... other data

Then finally you can do fun stuff like 最后,您可以做一些有趣的事情,例如

statuses = Status.objects.all().values('request__name')

or 要么

Status.objects.filter(request__name__contains="stack overflow")

According to the docs for the contenttypes framework : 根据文档的contenttypes框架

Due to the way GenericForeignKey is implemented, you cannot use such fields directly with filters ( filter() and exclude() , for example) via the database API. 由于GenericForeignKey的实现方式,您不能通过数据库API将此类字段直接用于过滤器(例如filter()exclude() )。

Since values() is a part of this API and is listed just two sections below filter() / exclude() in the docs for Aggregations and other QuerySet clauses , my guess is that is why your approach fails. 由于values()是此API的一部分,并且在文档中Aggregations和其他QuerySet子句的 filter() / exclude()下面仅列出了两部分,因此我猜测这就是您的方法失败的原因。

I would recommend this instead: 我建议改为:

status_list = Status.objects.all()
statuses = [{'request__name': status.request.name} for status in status_list]

Of course, the dict keys in the list comprehension can be whatever you'd like. 当然,列表理解中的dict键可以是您想要的任何键。 I left them as 'request__name' , since that is what you would've gotten if your approach had worked properly. 我将它们保留为'request__name' ,因为如果您的方法正常工作,这将是您得到的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM