基于对象的分页自定义查询集

时间:2018-09-19 12:50:38

标签: django django-rest-framework

我已经使用了基于对象的自定义查询集的API视图。我通过url中提供的pk获取对象。 我想返回带有分页对象的所有相关实例。

class ListVotedAPIView(generics.ListAPIView, VoteModelMixin):
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.voted(request)

    def get_queryset(self):
        instance = self.get_object()
        return services.get_voted(instance)

class VoteModelMixin:
    def voted(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

这是services.get_voted()

def get_voted(obj):
    """
    Return all users that voted `obj`.
    """
    obj_type = ContentType.objects.get_for_model(obj)
    return User.objects.filter(
        votes__content_type=obj_type,
        votes__object_id=obj.id
    )

问题在于get_object()是根据get_queryset()

定义的

我收到以下错误:RecursionError: maximum recursion depth exceeded 如何覆盖get_object()方法,该方法将可用于不同的模型?

已更新

class CommentLikeAPIView(generics.CreateAPIView, ):
    queryset = Comment.objects.all()
    serializer_class = LikeSerializer

    @staticmethod
    def get_contenttype():
        return ContentType.objects.get(model='comment')

    def get_serializer_context(self):
        """
        Extra context provided to the serializer class.
        """
        return {'request': self.request,
                'format': self.format_kwarg,
                'view': self,
                'content_type': self.get_contenttype(),
                'pk': self.kwargs.get('pk')}

1 个答案:

答案 0 :(得分:1)

问题是您根据get_queryset定义了get_object,但是get_object被定义为:

def get_object(self):
    # ...
    queryset = self.filter_queryset(self.get_queryset())

    # Perform the lookup filtering.
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field

    assert lookup_url_kwarg in self.kwargs, (
        'Expected view %s to be called with a URL keyword argument '
        'named "%s". Fix your URL conf, or set the `.lookup_field` '
        'attribute on the view correctly.' %
        (self.__class__.__name__, lookup_url_kwarg)
    )

    filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
    obj = get_object_or_404(queryset, **filter_kwargs)

    # May raise a permission denied
    self.check_object_permissions(self.request, obj)

    return obj

因此,这意味着.get_queryset(..)将调用.get_object(..),然后再次调用.get_queryset(..),此过程将继续进行,直到最终导致调用堆栈溢出。

因此,您将需要以某种方式破坏此相互递归,例如,通过实现一个不依赖于get_queryset的{​​{1}},或者通过覆盖不依赖于get_object的{​​{1}}的{​​{1}}。

例如:

get_object

(假设您只会提供get_queryset,那么也许您需要实现更复杂的功能)。

  

注意:您可能还希望在def get_object(self): # ... queryset = self.filter_queryset(this.model.objects.all()) # ... return get_object_or_404(queryset, **filter_kwargs)中传递Model*args,例如:

**kwargs