简体   繁体   English

Django Rest Framework OneToOneField相关的BooleanFilter

[英]Django Rest Framework OneToOneField related BooleanFilter

I'm using django with rest-framework. 我正在使用带有其余框架的django。

Now I have models with OneToOne relations: 现在,我具有与OneToOne关系的模型:

class ModelA(models.Model):
    pass

class ModelB(models.Model):
    a = models.OneToOneField(
        A, related_name='b')

And I have a ViewSet applied on A: 我有一个适用于A的ViewSet:

class ModelAViewSet(viewsets.ModelViewSet):
    queryset = ModelA.objects.all()
    serializer_class = ModelASerializer

Then, I want to add a BooleanFilter on ModelAViewSet to filter whether the ModelA object has a relating ModelB object. 然后,我想添加一个BooleanFilterModelAViewSet过滤是否ModelA对象有一个与ModelB对象。

And I tried the below: 我尝试了以下方法:

class ModelAViewSet(viewsets.ModelViewSet):
    class Filter(FilterSet):
        has_b = filters.BooleanFilter('b')
    queryset = ModelA.objects.all()
    serializer_class = ModelASerializer
    filter_fields = ['has_b']

So, if it works, we got: 因此,如果可行,我们得到:

  1. ?has_b=1 : returning all records without filtering; ?has_b=1 :不过滤就返回所有记录;
  2. ?has_b=2 : returning records which have relating ModelA object; ?has_b=2 :返回具有相关ModelA对象的记录;
  3. ?has_b=3 : returning records which NO NOT have relating ModelA object; ?has_b=3 :返回没有相关ModelA对象的记录;

It almost worked, except the case 3 above. 除了上面的情况3之外,它几乎奏效了。

So what's the correct way to do this? 那么正确的方法是什么?

from django_filters.rest_framework import FilterSet, filters

class Filter(FilterSet):
    has_b = filters.BooleanFilter(name='b', lookup_expr='isnull', exclude=True)

There are three changes here: 这里有三个变化:

  1. By importing from the rest_framework sub-package, an API-friendly BooleanWidget is used, so you can query ?has_b=true instead of ?has_b=1 . 通过从rest_framework子包导入,使用了API友好的BooleanWidget ,因此您可以查询?has_b=true而不是?has_b=1

  2. The filter is using an isnull lookup, which allows you to test for existence of a related model. 该过滤器正在使用一个非isnull查找,这使您可以测试相关模型的存在。

  3. b__isnull=True is testing for the lack of a related B , which is the opposite of what you want. b__isnull=True正在测试是否缺少相关的B ,这与您想要的相反。 Using exclude=True reverses the logic such that you instead filter for A s that have a related B instead. 使用exclude=True颠倒逻辑,以便您改为过滤具有相关B A

The equivalent .filter() calls: 等效的.filter()调用:

# before, incorrect
A.objects.filter(b=True)

# after, correct
A.objects.exclude(b__isnull=True)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM