【问题标题】:DRF canned filter - best practice?DRF 罐装过滤器 - 最佳实践?
【发布时间】:2016-08-02 15:17:49
【问题描述】:

我在我的 Django 应用程序中使用 Django REST Framework 来提供 API,并且最近添加了过滤。为了支持 UI 中的一些内容,我希望能够提供一些罐装/命名过滤器预设 - 例如,有一个 /api/tasks 视图集,可以为您提供所有任务的列表。任务具有已完成状态字段和完成日期。在 UI 中,我希望能够获取所有未完成或已完成但在过去几个小时内的任务的列表。这对于 Django 查询集来说很容易,但对于 DRF 过滤器则不然——最终目标是能够获取 /api/tasks?recent 或类似的东西。

有做这种事情的最佳实践吗?我可以使用不同的查询集字段创建新的 ViewSet,但是有更好的方法吗?

编辑:这是我目前的解决方案:

class PushTaskViewSet(AuthenticatedAPIModelViewSet):
    queryset = PushTask.objects.all()
    serializer_class = PushTaskSerializer       
    filter_fields = ('complete', 'date_created', 'date_completed', 'progress')

class RecentPushTaskViewSet(AuthenticatedAPIModelViewSet):
    # Get all tasks which are either incomplete, or only recently completed
    serializer_class = PushTaskSerializer

    def get_queryset(self):
        return PushTask.objects.filter(Q(complete=False) | Q(date_completed__gt=self.get_completed_threshold()))

    def get_completed_threshold(self):
        return datetime.now(tz=pytz.utc) - timedelta(hours=4)

router.register(r'master-tasks', viewsets.PushTaskViewSet)
router.register(r'recent-master-tasks', viewsets.RecentPushTaskViewSet, base_name="recent-master-tasks")

确实有效,但感觉很笨重。

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    您可以使用 DjangoFilterBackend。有关详细信息,请参阅documentation。 安装django-filter lib 后不要忘记在settings.py 文件中添加DjangoFilterBackend:

    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',
         )
    }
    

    然后在视图中使用它:

    class TaskListCreateView(ListCreateAPIView):
        filter_backends = (DjangoFilterBackend,)
        filter_fields = ('status', )
        serializer_class = TaskSerializer
    

    过滤对象的另一种方法是使用Filtering against query parameters。为此只是为了覆盖 get_queryset 方法:

    class TaskListCreateView(ListCreateAPIView):
        def get_queryset(self):
            queryset = Task.objects.all()
            status = self.request.query_params.get('status', None)
            if status:
                queryset = queryset.filter(status=status)
            return queryset
    

    【讨论】:

    • 这是真的(我在问题中所说的),但据我所知,它不支持 OR,而且我希望为常见情况提供一些更简单的东西。跨度>
    • @AnotherHowie 我扩展了我的答案
    猜你喜欢
    • 2015-11-16
    • 2019-11-30
    • 2021-08-03
    • 2014-05-23
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多