def partial(item): # resolve must be implemented on the field v, view_args, view_kwargs = field.resolve(item, field_name, self.request) if not v: return None if isinstance(self.request._request, EmbeddedRequest): request = self.request._request else: request = EmbeddedRequest(self.request) view_kwargs.update({"request": request, "is_embedded": True}) # Setup a view ourselves to avoid all the junk DRF throws in # v is a function that hides everything v.cls is the actual view class view = v.cls() view.args = view_args view.kwargs = view_kwargs view.request = request view.request.parser_context["kwargs"] = view_kwargs view.format_kwarg = view.get_format_suffix(**view_kwargs) _cache_key = (v.cls, field_name, view.get_serializer_class(), item) if _cache_key in CACHE.setdefault(self.request._request, {}): # We already have the result for this embed, return it return CACHE[self.request._request][_cache_key] # Cache serializers. to_representation of a serializer should NOT augment it's fields so resetting the context # should be sufficient for reuse if not view.get_serializer_class() in CACHE.setdefault(self.request._request, {}): CACHE[self.request._request][view.get_serializer_class()] = view.get_serializer_class()( many=isinstance(view, ListModelMixin) ) ser = CACHE[self.request._request][view.get_serializer_class()] try: ser._context = view.get_serializer_context() if not isinstance(view, ListModelMixin): ret = ser.to_representation(view.get_object()) else: queryset = view.filter_queryset(view.get_queryset()) page = view.paginate_queryset(queryset) ret = ser.to_representation(page or queryset) if page is not None: request.parser_context["view"] = view request.parser_context["kwargs"].pop("request") view.paginator.request = request ret = view.paginator.get_paginated_response(ret).data except Exception as e: ret = view.handle_exception(e).data # Allow request to be gc'd ser._context = None # Cache our final result CACHE[self.request._request][_cache_key] = ret return ret
def partial(item): # resolve must be implemented on the field v, view_args, view_kwargs = field.resolve(item, field_name, self.request) if not v: return None request = EmbeddedRequest(self.request) if not hasattr(request._request, '_embed_cache'): request._request._embed_cache = {} cache = request._request._embed_cache request.parents.setdefault(type(item), {})[item._id] = item view_kwargs.update({ 'request': request, 'is_embedded': True, }) # Setup a view ourselves to avoid all the junk DRF throws in # v is a function that hides everything v.cls is the actual view class view = v.cls() view.args = view_args view.kwargs = view_kwargs view.request = request view.request.parser_context['kwargs'] = view_kwargs view.format_kwarg = view.get_format_suffix(**view_kwargs) if not isinstance(view, ListModelMixin): try: item = view.get_object() except Exception as e: with transaction.atomic(): ret = view.handle_exception(e).data return ret _cache_key = (v.cls, field_name, view.get_serializer_class(), (type(item), item.id)) if _cache_key in cache: # We already have the result for this embed, return it return cache[_cache_key] # Cache serializers. to_representation of a serializer should NOT augment it's fields so resetting the context # should be sufficient for reuse if not view.get_serializer_class() in cache: cache[view.get_serializer_class()] = view.get_serializer_class()(many=isinstance(view, ListModelMixin), context=view.get_serializer_context()) ser = cache[view.get_serializer_class()] try: ser._context = view.get_serializer_context() if not isinstance(view, ListModelMixin): ret = ser.to_representation(item) else: queryset = view.filter_queryset(view.get_queryset()) page = view.paginate_queryset(getattr(queryset, '_results_cache', None) or queryset) ret = ser.to_representation(page or queryset) if page is not None: request.parser_context['view'] = view request.parser_context['kwargs'].pop('request') view.paginator.request = request ret = view.paginator.get_paginated_response(ret).data except Exception as e: with transaction.atomic(): ret = view.handle_exception(e).data # Allow request to be gc'd ser._context = None # Cache our final result cache[_cache_key] = ret return ret
def partial(item): # resolve must be implemented on the field v, view_args, view_kwargs = field.resolve(item, field_name, self.request) if not v: return None if isinstance(self.request, EmbeddedRequest): request = EmbeddedRequest(self.request._request) else: request = EmbeddedRequest(self.request) if not hasattr(request._request._request, '_embed_cache'): request._request._request._embed_cache = {} cache = request._request._request._embed_cache request.parents.setdefault(type(item), {})[item._id] = item view_kwargs.update({ 'request': request, 'is_embedded': True, }) # Setup a view ourselves to avoid all the junk DRF throws in # v is a function that hides everything v.cls is the actual view class view = v.cls() view.args = view_args view.kwargs = view_kwargs view.request = request view.request.parser_context['kwargs'] = view_kwargs view.format_kwarg = view.get_format_suffix(**view_kwargs) if not isinstance(view, ListModelMixin): try: item = view.get_object() except Exception as e: with transaction.atomic(): ret = view.handle_exception(e).data return ret _cache_key = (v.cls, field_name, view.get_serializer_class(), (type(item), item.id)) if _cache_key in cache: # We already have the result for this embed, return it return cache[_cache_key] # Cache serializers. to_representation of a serializer should NOT augment it's fields so resetting the context # should be sufficient for reuse if not view.get_serializer_class() in cache: cache[ view.get_serializer_class()] = view.get_serializer_class()( many=isinstance(view, ListModelMixin), context=view.get_serializer_context()) ser = cache[view.get_serializer_class()] try: ser._context = view.get_serializer_context() if not isinstance(view, ListModelMixin): ret = ser.to_representation(item) else: queryset = view.filter_queryset(view.get_queryset()) page = view.paginate_queryset( getattr(queryset, '_results_cache', None) or queryset) ret = ser.to_representation(page or queryset) if page is not None: request.parser_context['view'] = view request.parser_context['kwargs'].pop('request') view.paginator.request = request ret = view.paginator.get_paginated_response(ret).data except Exception as e: with transaction.atomic(): ret = view.handle_exception(e).data # Allow request to be gc'd ser._context = None # Cache our final result cache[_cache_key] = ret return ret