Advertisement
Guest User

Untitled

a guest
Apr 5th, 2021
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.16 KB | None | 0 0
  1. class PrefetchedFieldsSerializerMixin:
  2.     "Serializer mixin that helps to avoid N+1 issue."
  3.  
  4.     @staticmethod
  5.     def get_fields_to_be_prefetched(request):
  6.         """Basic method to be overridden.
  7.  
  8.        Returns fields should to be prefetched
  9.        before serialization to avoid N+1 issue.
  10.  
  11.        Args:
  12.            request: django request object
  13.  
  14.        Expected return:
  15.            fields: List[Union[str, Prefetch]]
  16.        """
  17.  
  18.         raise NotImplementedError
  19.  
  20.     def get_nested_fields_to_be_prefetched(
  21.         self, parent_field_prefix, request
  22.     ) -> List[Union[str, Prefetch]]:
  23.         """Doing the same as get_fields_to_be_prefetched
  24.        method, but also adds parent field as prefix.
  25.  
  26.        Should be used to avoid N+1 issue in case of
  27.        nested serialization of related field.
  28.        """
  29.  
  30.         prefetch_fields = []
  31.  
  32.         for nested_field in self.get_fields_to_be_prefetched(request):
  33.  
  34.             if isinstance(nested_field, str):
  35.                 nested_field = f"{parent_field_prefix}__{nested_field}"
  36.  
  37.             elif isinstance(nested_field, Prefetch):
  38.                 nested_field.add_prefix(parent_field_prefix)
  39.  
  40.             else:
  41.                 message = f"""
  42.                Type {type(nested_field)} cannot be used in prefetch_related
  43.                method. Use str or Prefetch object instead.
  44.                """
  45.  
  46.                 raise TypeError(message)
  47.  
  48.             prefetch_fields.append(nested_field)
  49.  
  50.         return prefetch_fields
  51.  
  52.     def to_representation(self, instance):
  53.         return super().to_representation(self._prefetch_fields(instance))
  54.  
  55.     def _prefetch_fields(self, instance):
  56.         """Prefetches fields in case ther are't prefetched yet.
  57.  
  58.        This method solves errors when serializer includes dynamic
  59.        fields generated by Prefetch() objects if they are not prefetched yet."""
  60.  
  61.         if not hasattr(instance, "_prefetched_objects_cache"):
  62.             prefetch_fields = self.get_fields_to_be_prefetched(
  63.                 self.context.get("request")
  64.             )
  65.             prefetch_related_objects([instance], *prefetch_fields)
  66.         return instance
  67.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement