def filter_queryset(self, request: Request, queryset: QuerySet, view: GenericViewSet): if (not issubclass(view.get_serializer_class(), FlexFieldsSerializerMixin) or request.method != "GET"): return queryset auto_remove_fields_from_query = getattr( view, "auto_remove_fields_from_query", True) auto_select_related_on_query = getattr(view, "auto_select_related_on_query", True) required_query_fields = list(getattr(view, "required_query_fields", [])) serializer = view.get_serializer( # type: FlexFieldsSerializerMixin context=view.get_serializer_context()) serializer.apply_flex_fields() model_fields = [ self._get_field(field.source, queryset.model) for field in serializer.fields.values() if self._get_field(field.source, queryset.model) ] nested_model_fields = [ self._get_field(field.source, queryset.model) for field in serializer.fields.values() if self._get_field(field.source, queryset.model) and field.field_name in serializer.expanded_fields ] if auto_remove_fields_from_query: queryset = queryset.only(*(required_query_fields + [ model_field.name for model_field in model_fields if not model_field.is_relation or model_field.many_to_one ])) if auto_select_related_on_query and nested_model_fields: queryset = queryset.select_related( *(model_field.name for model_field in nested_model_fields if model_field.is_relation and model_field.many_to_one)) queryset = queryset.prefetch_related( *(model_field.name for model_field in nested_model_fields if model_field.is_relation and not model_field.many_to_one)) return queryset
def _get_not_detail_actions(self, viewset: viewsets.GenericViewSet) -> list: not_detail_actions = [] list_action = getattr(viewset, "list", None) if list_action: not_detail_actions.append(list_action) create_action = getattr(viewset, "create", None) if create_action: not_detail_actions.append(create_action) actions = viewset.get_extra_actions() for view_action in actions: if not view_action.detail and view_action.__name__ != "permissions": not_detail_actions.append(view_action) return not_detail_actions
def paged_response( *, view: viewsets.GenericViewSet, queryset: Optional[QuerySet] = None, status_code: Optional[int] = None, ): """ paged_response can be used when there is a need to paginate a custom API endpoint. Usage: class UsersView(ModelViewSet): ... @action( ['get'], detail=True, serializer_class=PostSerializer, filterset_class=PostsFilterSet, ) def posts(self, request: Request, pk: Optional[str] = None): queryset = Post.objects.filter(user=self.get_object()) return paged_response(view=self, queryset=queryset) :param view: any instance that statisfies the GenericViewSet interface :param queryset: Optional django.db.models.QuerySet. Default: get_queryset output :param status_code: Optional int :return: rest_framework.response.Response """ status_code = status_code or status.HTTP_200_OK queryset = queryset or view.get_queryset() queryset = view.filter_queryset(queryset) page = view.paginate_queryset(queryset) if page is not None: serializer = view.get_serializer(page, many=True) return view.get_paginated_response(serializer.data) serializer = view.get_serializer(queryset, many=True) return response.Response(serializer.data, status=status_code)
def finalize_response(self, request, response, *args, **kwargs): request._request.CORS = self.cors_allowed_methods return GenericViewSet.finalize_response(self, request, response, *args, **kwargs)
def __init__(self, **kwargs): GenericViewSet.__init__(self, **kwargs) self.name = self.__class__.__name__.replace('ViewSet', '') self.filter_class = eval("{}Filter".format(self.name))
def test_override_serializer(): view = GenericViewSet() with override_serializer(view, DummySerializer): assert view.get_serializer_class() == DummySerializer
def __init__(self, **kwargs): GenericViewSet.__init__(self, **kwargs) self.name = self.__class__.__name__.replace('ViewSet', '')