django Rest Framework - 具有自定义列表视图和URL参数的ViewSet

时间:2018-03-26 15:39:31

标签: django django-rest-framework

我有以下设置:

我想列出特定年份的所有假期。这就是我省略默认列表视图并实现我自己的原因:

class HolidayViewSet(mixins.RetrieveModelMixin, GenericViewSet):
@list_route()
def year(self, request, year=get_today().year):
    public_holidays = self.get_queryset().filter(date__year=year)
    page = self.paginate_queryset(public_holidays)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)
    serializer = self.get_serializer(public_holidays, many=True)
    return Response(serializer.data)

如果我使用默认/假日/年/我得到当年的结果。

但是当我尝试传递一个参数时,我会得到一个404. 404页面(在调试模式下)甚至会显示正确的URL模式:

api/v1/ ^holiday/year/$ [name='holiday-year']
api/v1/ ^holiday/year\.(?P<format>[a-z0-9]+)/?$ [name='holiday-year']

documentation遗憾的是,这方面没有涵盖。

为什么我的holiday/year/2017路线无效?

谢谢! 罗恩

3 个答案:

答案 0 :(得分:1)

好的,我的解决方法是使用django-filter

我的过滤器:

class HolidayFilter(filters.FilterSet):
    """
    This filter can be used to filter holidays by different values in API views or viewsets.
    See http://django-filter.readthedocs.io/en/1.1.0/guide/rest_framework.html
    """
    year = filters.NumberFilter(name='date', lookup_expr='year')

    class Meta:
        model = Holiday
        fields = ['date']

我的观点:

class HolidayListViewSet(ModelViewSet):

    def list(self, request, *args, **kwargs):
        # Apply filters
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        # Pagination
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # Serializer
        serializer = self.get_serializer(queryset, many=True)
        # Response
        return Response(serializer.data)

网址:

/api/v1/holiday/?year=2016

感谢您的支持,也许这有助于其他人!

答案 1 :(得分:0)

DRF区分listdetail个请求。 list请求不应该有额外的路径参数(即/{id}),而detail请求则相反,由它定义。

@list_route装饰器创建/holiday/year端点意味着什么,@detail_route将创建/holiday/{id}/year端点。

答案 2 :(得分:0)

我认为我的方法很简单,但很有用。只需确定您的路由器,如下所示:

urlpatterns += [
    path(r'holiday/<int:year>/', TestListView.as_view()),
]

URL:

api / v1 / holiday / 2016 /

然后按以下方式创建视图:

class TestListView(generics.ListAPIView):
    serializer_class = TestSerializer

    def get(self, request, *args, **kwargs):
        year = kwargs.get('year', '')
        query_set = Test.objects.filter(year__exact=year) # Test is my test model
        serializer = self.get_serializer(query_set, many=True)
        return Response(serializer.data)