Last active
July 13, 2022 15:29
-
-
Save stuaxo/1e5f272d84e68eceaddafa0c7f9d37ae to your computer and use it in GitHub Desktop.
Split polymorphic ctype objects into groups by type.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def group_by_type(models): | |
""" | |
Yield a sequence of query sets, where each one only has one Polymorphic ctype, this | |
makes it possible to use prefetch and select_related with the resulting querysets. | |
""" | |
pks = models.values_list("pk", flat=True) | |
polymorphic_ctypes = models.non_polymorphic().distinct("polymorphic_ctype_id").values_list("polymorphic_ctype", flat=True) | |
for polymorphic_ctype in polymorphic_ctypes: | |
# Query contenttypes to get the concrete class instance | |
klass = ContentType.objects.get_for_id(polymorphic_ctype).model_class() | |
yield klass.objects.filter(pk__in=pks) | |
def select_related_copyable_fields(self): | |
""" | |
Split models into separate querysets, using group_by_type and call select_related on any related fields | |
found in the `copyable_fields` attribute. | |
""" | |
pks = models.values_list("pk", flat=True) | |
for qs in group_by_type(models): | |
# Work out which fields to use in select_related | |
related_fields = [field.name for field in qs.model.copyable_fields if hasattr(field, "related_query_name")] | |
yield qs.select_related(*related_fields).filter(pk__in=pks) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment