-
Notifications
You must be signed in to change notification settings - Fork 65
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
Add prefetch_related support to ParentalManyToManyField #122
Conversation
def _apply_rel_filters(self, queryset): | ||
# Required for get_prefetch_queryset. | ||
return queryset._next_is_sticky() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chosak This method doesn't appear to be needed any longer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ababic thanks for taking a look at this PR.
The Django 1.10 release notes say that
If you defined a custom manager class available through
prefetch_related()
you must make sure it defines a_apply_rel_filters()
method.
Prior to Django 2.0 this wasn't technically required yet, but 2.0 removed a shim that allowed that:
The shim for supporting custom related manager classes without a
_apply_rel_filters()
method is removed.
_apply_rel_filters
gets called by Django code here. Note that the DeferringRelatedManager used for ParentalKey also defines this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay. That makes sense! In that case, ignore me! This is super impressive BTW... I've had a crack at this before and it's not the nicest part of Django to delve into.
I'll try to give this a whirl today in a 2.8 project. It'll make a huge difference to performance on at least one of my active projects! |
@ababic Haven't dug into the logic, but assuming Django's internal mechanisms call
|
This commit adds support for prefetch_related on ParentalManyToManyFields. Consider for example these models: class Author(models.Model): ... class Article(ClusterableModel): authors = ParentalManyToManyField(Author) With this change, you can create a query like this: articles = Article.objects.prefetch_related('authors') and then subsequent references to article authors won't invoke additional database queries. This implementation is modeled after the current implementation of Django's ManyRelatedManager.get_prefetch_queryset. Closes issue 101.
787bead
to
1699718
Compare
@ababic thanks very much for the review. @gasman, thanks for the thoughtful suggestions. I've pushed a commit that adds the first test you mention, to confirm that prefetching on a fake queryset works as expected. Handling your second case is a little more tricky. The test you propose fails right now, because right now One possible fix that does seem to work for your proposed test would be for this project to use Regardless, I tend to agree that this is out of scope for this more immediate fix to get |
This commit adds support for prefetch_related on ParentalManyToManyFields. Consider for example these models:
With this change, you can create a query like this:
and then subsequent references to article authors won't invoke additional database queries.
This implementation is modeled after the current implementation of Django's
ManyRelatedManager.get_prefetch_queryset
.Closes #101.
I've done limited testing on this with Wagtail 2.3 (see wagtail/wagtail#4784), but it'd be great to get others testing against more recent versions.