我使用Django REST Framework构建了一个REST端点。
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginModel usr)
{
if (usr.UserName=="random"&&usr.Password=="randPassword")
{
Session["Username"] = usr.UserName.ToString();
FormsAuthentication.SetAuthCookie(user.UserName, false);
return RedirectToAction("Success","Account",new {new {Name=usr.UserName}});
}
else
{
ModelState.AddModelError("", "UserName or Password is Wrong");
return View();
}
}
现在,如果我提出这样的请求:
class PersonFilter(django_filters.FilterSet):
id = django_filters.NumberFilter(name="id", lookup_type="gt")
first_name = django_filters.CharFilter(name="first_name", lookup_type="icontains")
last_name = django_filters.CharFilter(name="last_name", lookup_type="icontains")
class Meta:
model = Person
fields = ('id', 'first_name', 'last_name', 'last_mod')
class PersonModelViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Person.objects.none()
filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
pagination_class = StandardResultsSetPagination
ordering_fields = ('id', 'first_name', 'last_name', 'last_mod')
ordering = ('last_mod', 'id')
filter_class = PersonFilter
这只返回名字和姓氏都包含" foo"的那些对象。我想返回名字包含" foo"或姓氏包含" foo"。
我想知道URL参数中是否有可用的符号,这意味着过滤器之间的逻辑或关系。
一种解决方法是向端点发出两个单独的AJAX查询,但这需要额外的工作来统一结果。
答案 0 :(得分:3)
不幸的是,目前的django_filter
实施无法实现。每个过滤器都会就地修改查询集,而不是返回Q
对象,这可以根据您的喜好加入。您可以尝试重写FilterSet.qs()
方法并在self._qs.query.where
上执行一些黑魔法,以使用OR
重新组合子句。另请参阅editing the queryset filters上的问题。
更新:只要Django处理SQL注入尝试真的很好,你就可以使用类似的东西:
qs.filter(map(operators.or_, [Q(k=v) for k, v in request.GET.items()]))
,但在投入生产之前肯定需要进行一些验证。
答案 1 :(得分:2)
我还想做类似的事情,最终使用django-filter创建了一个自定义过滤器,希望这会有所帮助:
class NameFilter(django_filters.CharFilter):
def filter(self, qs, value):
if value:
return qs.filter(Q(**{first_name+'__'+self.lookup_expr: value}) |
Q(**{last_name+'__'+self.lookup_expr: value}))
return qs
class PersonFilter(django_filters.rest_framework.FilterSet):
name = NameFilter(lookup_expr='icontains')
/ api / rest / v1 / Person?name = foo&page_size = 10
这不是一个非常通用的解决方案,而是一个如何创建自己的过滤器的示例,它的通用性取决于您的代码实现。
答案 2 :(得分:1)
您可以使用复杂的单词并使用不同的前缀(不仅是'q')
query_reg = self.request.GET.get("r")
if query_reg:
queryset = queryset.filter(
Q(region=query_reg)
)
query_reg_air = self.request.GET.get("ra")
if query_reg_air:
queryset = queryset.filter(
Q(region=query_reg_air.split('_')[0]) &
Q(min_air_flow__lte=query_reg_air.split('_')[1]) &
Q(max_air_flow__gte=query_reg_air.split('_')[1]) |
Q(region=query_reg_air.split('_')[0]) &
Q(min_air_flow__lte=str(float(query_reg_air.split('_')[1]) * 1.2)) &
Q(max_air_flow__gte=str(float(query_reg_air.split('_')[1])))
# Q(query__range=(min_air_flow, max_air_flow))
).order_by('-KPC')