Skip to content

Instantly share code, notes, and snippets.

@stuaxo
Last active July 13, 2022 15:29
Show Gist options
  • Save stuaxo/1e5f272d84e68eceaddafa0c7f9d37ae to your computer and use it in GitHub Desktop.
Save stuaxo/1e5f272d84e68eceaddafa0c7f9d37ae to your computer and use it in GitHub Desktop.
Split polymorphic ctype objects into groups by type.
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