我有一个简单的模型:
class Ingredient(models.Model):
name = models.CharField(max_length=30)
我正在为api端点使用django rest框架。
class IngredientListAPIView(ListAPIView):
queryset = Ingredient.objects.all()
serializer_class = IngredientListSerializer
filter_backends = [OrderingFilter]
我希望我的两个终点输出为:
?ordering=name -- i want the ordering to be case-insensitive
?ordering=-name -- i want the ordering to be case-insensitive
实现这一目标的唯一方法是创建
class CaseInsensitiveOrderingFilter(OrderingFilter):
def filter_queryset(self, request, queryset, view):
ordering = self.get_ordering(request, queryset, view)
if ordering:
new_ordering = []
for field in ordering:
if field.startswith('-'):
new_ordering.append(Lower(field[1:]).desc())
else:
new_ordering.append(Lower(field).asc())
return queryset.order_by(*new_ordering)
return queryset
然后
class IngredientListAPIView(ListAPIView):
queryset = Ingredient.objects.all().order_by(Lower('name'))
serializer_class = IngredientListSerializer
filter_backends = [CaseInsensitiveOrderingFilter]
但现在我访问以下端点
?ordering=id -- it shows 1,10,11,12
?ordering=-id -- it shows 99,98 ..100..
如果我使用filter_backends = [OrderingFilter]
代替filter_backends = [CaseInsensitiveOrderingFilter]
?ordering=id -- it shows 1,2,3,4,
?ordering=-id -- it shows 220,221,220
那么如何告诉Django使用
filter_backends = [CaseInsensitiveOrderingFilter] for name field and
filter_backends = [OrderingFilter] for id field
答案 0 :(得分:0)
<强> views.py 强>
class IngredientListAPIView(ListAPIView):
queryset = Ingredient.objects.all()
serializer_class = IngredientListSerializer
def filter_queryset(self, queryset):
if "name" in self.request.query_params.get("ordering"):
return CaseInsensitiveOrderingFilter().filter_queryset(self.request, queryset, self)
else:
queryset = OrderingFilter().filter_queryset(self.request, queryset, self)
return SearchFilter().filter_queryset(self.request, queryset, self)
答案 1 :(得分:0)
我建议为不区分大小写的字段设置特定的类属性
class IngredientListAPIView(ListAPIView):
queryset = Ingredient.objects.all().order_by(Lower('name'))
serializer_class = IngredientListSerializer
filter_backends = [CaseInsensitiveOrderingFilter]
ordering_fields = () # include both normal and case insensitive fields
ordering_case_insensitive_fields = () # put here only case insensitive fields
然后您的自定义排序类将是:
class CaseInsensitiveOrderingFilter(OrderingFilter):
def filter_queryset(self, request, queryset, view):
ordering = self.get_ordering(request, queryset, view)
insensitive_ordering = getattr(view, 'ordering_case_insensitive_fields', ())
if ordering:
new_ordering = []
for field in ordering:
if field in insensitive_ordering:
new_ordering.append(Lower(field[1:]).desc() if field.startswith('-') else Lower(field).asc())
else:
new_ordering.append(field)
return queryset.order_by(*new_ordering)
return queryset