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