Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class PrefetchedFieldsSerializerMixin:
- "Serializer mixin that helps to avoid N+1 issue."
- @staticmethod
- def get_fields_to_be_prefetched(request):
- """Basic method to be overridden.
- Returns fields should to be prefetched
- before serialization to avoid N+1 issue.
- Args:
- request: django request object
- Expected return:
- fields: List[Union[str, Prefetch]]
- """
- raise NotImplementedError
- def get_nested_fields_to_be_prefetched(
- self, parent_field_prefix, request
- ) -> List[Union[str, Prefetch]]:
- """Doing the same as get_fields_to_be_prefetched
- method, but also adds parent field as prefix.
- Should be used to avoid N+1 issue in case of
- nested serialization of related field.
- """
- prefetch_fields = []
- for nested_field in self.get_fields_to_be_prefetched(request):
- if isinstance(nested_field, str):
- nested_field = f"{parent_field_prefix}__{nested_field}"
- elif isinstance(nested_field, Prefetch):
- nested_field.add_prefix(parent_field_prefix)
- else:
- message = f"""
- Type {type(nested_field)} cannot be used in prefetch_related
- method. Use str or Prefetch object instead.
- """
- raise TypeError(message)
- prefetch_fields.append(nested_field)
- return prefetch_fields
- def to_representation(self, instance):
- return super().to_representation(self._prefetch_fields(instance))
- def _prefetch_fields(self, instance):
- """Prefetches fields in case ther are't prefetched yet.
- This method solves errors when serializer includes dynamic
- fields generated by Prefetch() objects if they are not prefetched yet."""
- if not hasattr(instance, "_prefetched_objects_cache"):
- prefetch_fields = self.get_fields_to_be_prefetched(
- self.context.get("request")
- )
- prefetch_related_objects([instance], *prefetch_fields)
- return instance
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement