python - Django Rest Framework - 嵌套一对多的过滤器

标签 python django django-rest-framework django-filter

我想要实现的目标:

我想要一份包含各自任务的用户列表,并根据任务开始日期进行过滤。

# Pseudo json
User 1
  - mission 1
  - mission 2
User 2
  - mission 1
  - mission 2
  - mission 3

我的数据结构:

模型:

class Mission(models.Model):
  start = models.DateTimeField()
  user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="missions")

序列化器:

# Mission
class MissionSerializer(serializers.ModelSerializer):
  class Meta:
    model  = Mission
    fields = (
      'start',
      'end',
    )

# User
class UserSerializer(serializers.ModelSerializer):
  missions = MissionSerializer(many=True)
  class Meta:
    model  = MyUser
    fields = (
      'username',
      'missions',
    )

View 集:

# Filter
class UserFilter(django_filters.FilterSet):
  class Meta:
    model  = MyUser
    fields = {
      'missions__start': ['gte','lt']
    }

# Viewset
class UserViewset(viewsets.ModelViewSet):
  filter_backends  = (filters.OrderingFilter, filters.DjangoFilterBackend,)
  filter_class     = UserFilter
  serializer_class = UserSerializer

  @list_route(methods=['get'])
  def listCalendar(self, request):
    prefetched_missions = Prefetch('missions', queryset=Mission.objects.all())
    objects_list = MyUser.objects.prefetch_related( prefetched_missions )
    objects_list = self.filter_queryset(objects_list)
    serializer   = UserSerializer(objects_list, many=True)
    return Response(serializer.data)

我的问题:

调用此 URL 时:

/api/users/listCalendar/?start__gte=2015-06-29&start__lt=2015-08-10

过滤器被忽略了,我想不出让它工作的方法。 我的直觉是问题出在 ViewSet 中的 Mission.objects.all() 上,它可能类似于:Mission.objects.filter(*But what here?*)

非常感谢任何帮助!


编辑 1:

有一些进步!但仍然无法正常工作...正如您建议的 Mark Galloway 我尝试调用以下网址:

/api/users/listCalendar/?missions__start__gte=2015-06-29&missions__start__lt=2015-08-10

但这是执行的查询:

SELECT "app_myuser"."id", "app_myuser"."username"
FROM "app_myuser"
INNER JOIN "app_mission" ON ( "app_myuser"."id" = "app_mission"."user_id" )
INNER JOIN "app_mission" T4 ON ( "app_myuser"."id" = T4."user_id" )
WHERE ("app_mission"."start" >= '2015-07-06T00:00:00+00:00'::timestamptz
AND T4."start" < '2015-07-12T00:00:00+00:00'::timestamptz)
ORDER BY "app_myuser"."username" ASC;

如您所见,有 2 个 INNER JOIN 而不是 1 个。出于某些原因,它采用 2 个过滤字段,就好像它们在单独的表中一样。结果是我的结果重复了。

最佳答案

这里有三件事

首先,您缺少 the DjangoFilterBackend 在你的 filter_backends list .这就是告诉 Django REST 框架查看 filter_class 的内容。并对请求应用相关的过滤,没有它你的 filter_class将被忽略(如您所见)。

class UserViewset(viewsets.ModelViewSet):
    filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend, )
    filter_class = UserFilter
    serializer_class = UserSerializer

其次,您希望能够使用 startend查询参数,但告诉 django-filter 查看 missions__start Meta.fields 中的字段.您可以通过在 FilterSet 上手动定义字段来解决此问题用你的别名

class UserFilter(django_filters.FilterSet):
    start_gte = django_filter.DateTimeFilter(name='missions__start', lookup_type='gte', distinct=True)
    start_lte = django_filter.DateTimeFilter(name='missions__start', lookup_type='lte', distinct=True)

    end_gte = django_filter.DateTimeFilter(name='missions__end', lookup_type='gte', distinct=True)
    end_lte = django_filter.DateTimeFilter(missions__name='end', lookup_type='lte', distinct=True)

    class Meta:
        model  = MyUser
        fields = ('start_gte', 'start_lte', 'end_gte', 'end_lte', )

或者通过仅引用查询参数将获得完整值(missions__start_gte 而不是 start_gte)。

三、因何INNER JOIN查询跨多个表工作,在执行影响单个用户下的多个任务的过滤器时,您将收到重复的值。您可以使用 the distinct argument 解决此问题在您的过滤器中(如上所示)或添加 .distinct()filter_queryset 中过滤器调用的末尾.

关于python - Django Rest Framework - 嵌套一对多的过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31214542/

相关文章:

python - 可执行的 Snakefile

python XML 元素删除错误

python - 递归计算 Pandas 数据框中 parent 和 child 之间的比率

python - 单类机争夺计划

python - Django/Python 中按查询集计数排序列表

javascript - Django 循环中的多个 JQuery 倒计时

django - 使用 create-react-app 自定义静态文件路径?

Django 休息框架 : Dynamically return subset of fields

java - 在 Retrofit 2 中添加第三个 @Field 时出现 NoSuchMethodError

ModelViewSet 中的 django-rest 自定义 url