Python Django rest framework自定义筛选器后端数据复制

Python Django rest framework自定义筛选器后端数据复制,python,django,django-rest-framework,Python,Django,Django Rest Framework,我试图使我的自定义过滤器和排序后端与django rest框架中的默认搜索后端一起工作。过滤和排序彼此完美配合,但当查询中包含搜索,并且我尝试按对象名称对查询进行排序时,就会发生数据重复 我试着打印查询和查询大小,但当我在过滤器中记录它时似乎还可以,但在响应中我有不同的对象计数性别。过滤查询中79个对象,最终结果中170个重复对象 这是我的filterset课程 class PhonesFilterSet(rest_filters.FilterSet): brands = InListF

我试图使我的自定义过滤器和排序后端与django rest框架中的默认搜索后端一起工作。过滤和排序彼此完美配合,但当查询中包含搜索,并且我尝试按对象名称对查询进行排序时,就会发生数据重复

我试着打印查询和查询大小,但当我在过滤器中记录它时似乎还可以,但在响应中我有不同的对象计数性别。过滤查询中79个对象,最终结果中170个重复对象

这是我的filterset课程

class PhonesFilterSet(rest_filters.FilterSet):
    brands = InListFilter(field_name='brand__id')
    os_ids = InListFilter(field_name='versions__os')
    version_ids = InListFilter(field_name='versions')
    launched_year_gte = rest_filters.NumberFilter(field_name='phone_launched_date__year', lookup_expr='gte')
    ram_gte = rest_filters.NumberFilter(field_name='internal_memories__value', method='get_rams')
    ram_memory_unit = rest_filters.NumberFilter(field_name='internal_memories__units', method='get_ram_units')

    def get_rams(self, queryset, name, value):
        #here is the problem filter
        #that not works with ordering by name
        q=queryset.filter(Q(internal_memories__memory_type=1) & Q(internal_memories__value__gte=value))
        print('filter_set', len(q))
        print('filter_set_query', q.query)
        return q


    def get_ram_units(self, queryset, name, value):
        return queryset.filter(Q(internal_memories__memory_type=1) & Q(internal_memories__units=value))


    class Meta:
        model = Phone
        fields = ['brands', 'os_ids', 'version_ids', 'status', 'ram_gte']
我的订购课:

class CustomFilterBackend(filters.OrderingFilter):
    allowed_custom_filters = ['ram', 'camera', 'year']

    def get_ordering(self, request, queryset, view):
        params = request.query_params.get(self.ordering_param)

        if params:
            fields = [param.strip() for param in params.split(',')]
            ordering = [f for f in fields if f in self.allowed_custom_filters]
            if ordering:
                return ordering

        # No ordering was included, or all the ordering fields were invalid

        return self.get_default_ordering(view)


    def filter_queryset(self, request, queryset, view):
        ordering = self.get_ordering(request, queryset, view)
        if ordering:
            if 'ram' in ordering:
                max_ram = Max('internal_memories__value', filter=Q(internal_memories__memory_type=1))
                queryset = queryset.annotate(max_ram=max_ram).order_by('-max_ram')
            elif 'camera' in ordering:
                max_camera = Max('camera_pixels__megapixels', filter=Q(camera_pixels__camera_type=0))    
                queryset = queryset.annotate(max_camera=max_camera).order_by('-max_camera')            
            elif 'year' in ordering:
                queryset = queryset.filter(~Q(phone_released_date=None)).order_by('-phone_released_date__year')
            elif 'name' in ordering:
                #here is the problem ordering
                #thats not working with filter
                #with one to many relations
                queryset = queryset.order_by('-brand__name', '-model__name')


        return queryset
视图集类:

class PhoneViewSet(viewsets.ModelViewSet):
    queryset = Phone.objects.all()
    serializer_class = PhoneSerializer
    filter_backends = (filters.SearchFilter, CustomFilterBackend, django_filters.rest_framework.DjangoFilterBackend)
    search_fields = ('brand__name', 'model__name')
    ordering_fields = ('brand__name', 'model__name')
    filter_class = PhonesFilterSet
因此,当我使用过滤器和搜索进行排序时,我希望不会出现数据重复。我的问题是,为什么在过滤器和响应中对象的数量不同,其中数据变得重复?我不知道从这里开始调试。提前感谢。

使用distinct应该可以解决以下问题:

返回在其SQL查询中使用SELECT DISTINCT的新查询集。这将从查询结果中消除重复的行

默认情况下,查询集不会消除重复的行。实际上,这很少是一个问题,因为像Blog.objects.all这样的简单查询不会引入重复结果行的可能性。但是,如果查询跨越多个表,则在计算QuerySet时可能会得到重复的结果。这时你会使用distinct

但是请注意,您仍然可能会得到重复的结果:

order_by调用中使用的任何字段都包含在SQL SELECT列中。当与distinct结合使用时,有时会导致意外结果。如果按相关模型中的字段排序,则这些字段将添加到选定的列中,并且它们可能会使其他重复行看起来不同。因为额外的列不会出现在返回的结果中,它们只是为了支持排序,所以有时看起来像是返回了非不同的结果

如果您使用的是PostgreSQL,则可以指定应应用DISTINCT的字段的名称。这可能会有帮助。我不确定。有关这方面的更多信息,请参见上面的链接

因此,我将在方法中返回queryset.distinct,在这些方法中,您评论说您遇到了问题。我不会像我在上面的评论中写的那样将其应用于调试,因为简单的查询不需要它。

请在PhoneViewSet中尝试queryset=Phone.objects.all.distinct