Reputation: 620
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
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?
Upvotes: 1
Views: 2541
Reputation: 620
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")
Upvotes: 3
Reputation: 2157
According to the docs for the contenttypes framework:
Due to the way
GenericForeignKey
is implemented, you cannot use such fields directly with filters (filter()
andexclude()
, for example) via the database API.
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.
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. I left them as 'request__name'
, since that is what you would've gotten if your approach had worked properly.
Upvotes: 1