-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ListSerializer.to_representation does not respect prefetches #2704
Comments
Closing this as duplicate of #2442. |
@xordoquy this is actually a distinct issue that only comes up when you use the My use case is providing a flexible GET API that provides filtering on secondary related resources. |
Will take time to investigate this further then |
This is to force the QS reevaluation when someone writes the view class such as:
Which means that the queryset will be evaluated at the class declaration rather than on per request basis if we didn't force the reevaluation. |
@tomchristie do we really need the queryset reevaluation ? |
This isn't a major blocker right now (e.g. we've been able to work around it with a custom ListSerializer and/or custom relation field that proxies a serializer) However, perhaps there should be an setting that allows you to toggle this behavior, which can be on by default for newcomers per your example? |
@xordoquy Sorry, which one specifically? |
@tomchristie the one we have in serializers:
The more I think about it the more I believe it is encouraging bad patterns (i.e. queryset evaluated where they shouldn't be) |
We certainly need it for the Manager case - I expect we do need it for the queryset case too, but it'd be worth look at the history for that line. |
Is this something that's documented? It seems strange that calling |
@kevin-brown adding |
My question is specifically about the different query. I understand that it should be re-evaluated, which would be fine if it triggered the same query, but I don't understand why it's being evaluated using a different query. I'm specifically referencing this
|
@kevin-brown you probably have a point there. It should have been the very same request played another time. Probably an issue on the Django part. |
@kevin-brown @xordoquy this does seem like a Django bug / undesired behavior related to the way querysets are cloned, which is happening during calls to The prefetch context is lost during cloning; also note that calling
|
Have closed #2727 as a duplicate of this, although possible that we can more broadly state the issue, as it's probably not just |
TODO to progress this issue:
Note that #2727 includes a very trival example for demonstrating the behavior that doesn't rely on |
Working on #3076 to hopefully progress this issue. |
Closed by #3076. |
Thanks for the fix guys :) |
😄 |
Update: Related to #2727 - @tomchristie
I noticed some undesirable behavior around
ListSerializer
's implementation ofto_representation
in the context of relations prefetched with Django 1.7's Prefetch object.I am talking about this block of code:
To demonstrate the problem, consider a request made to fetch all
auth.User
s and their relatedauth.Group
s matching a certain filter. This can be done withPrefetch
like so:Lets look at the first user and his prefetched groups:
... so far, so good. Now let's add DRF into the mix; I have a
UserSerializer
and a relatedGroupSerializer
:If I call
UserSerializer(users_with_test_groups, many=True).data
, I expect to see my first user returned with only those related groups that containtest
. But I actually see ALL groups related to that user!This is because calling
.all()
on a filtered managed queryset will re-evaluate that queryset as if it has no filters:This took a while to figure out and seems like bizarre behavior. Why is calling
.all()
on a queryset necessary when you can just iterate over it?As a workaround, I have started using a custom
ListSerializer
that never calls.all()
. Interested to hear if anybody else has run into this or tried using DRF Serializers together with thePrefetch
object.The text was updated successfully, but these errors were encountered: