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
Fixed #30493 -- Fixed prefetch_related() for GenericRelation with different content types. #11423
Conversation
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.
@cansarigol Thanks for this patch 👍 I left some comments.
@felixxm thanks for your review. I applied your comments, could you review it? |
ba3b8d1
to
ece29ed
Compare
I rebased from master, moved |
Should we use |
I don't think so because it is not a "sub-test" (we're not testing different conditions here), all three will work or not. |
I got it thanks |
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.
I think it might be worth adding some form of memoization to get_content_type
calls by (obj._state.db, obj.__class__)
in get_prefetch_queryset
as there will potentially be lot of them and they'll result in a non negligible amount of work.
@charettes Thanks for the review 👍 |
@felixxm I know but each |
I will add it tomorrow. |
@charettes I added basic memoization. What do you think? |
What if we add |
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.
This memoize_content_type
seems to be working but is not kept in sync with ContentType.objects.clear_cache()
.
I like @cansarigol's idea of caching it at __init__
though which should be doable given all objects should be on the same database.
e.g. in __init__
self.get_content_type = partial(
ContentType.objects.db_manager(instance._state.db).get_for_model,
for_concrete_model=rel.field.for_concrete_model,
)
self.content_type = self.get_content_type(instance)
…ferent content types. Co-Authored-By: Mariusz Felisiak <felisiak.mariusz@gmail.com> Thanks Simon Charette for the review.
@charettes Thanks 🏆 I updated PR. |
}) | ||
for content_type_id, objs in itertools.groupby( | ||
sorted(instances, key=lambda obj: self.get_content_type(obj).pk), | ||
lambda obj: self.get_content_type(obj).pk, |
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.
This seems rather inefficient... Doesn't self.get_content_type(obj)
execute a query?
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.
@pope1ni no, it's heavily cached as it's using ContentType.objects.get_for_model
.
Ticket: #30493