构建请求 URL 以通过同一字段多次过滤 Django 查询集
Build request URL to filter Django queryset multiple times by the same field
我想通过同一字段多次过滤 Django 查询集,使用 Q
到 include/exclude 此字段中具有特定值的记录。
我将使用示例模型来说明我的情况。假设我有一个带有字段 status
的 Record
模型。该字段可以是三种状态之一 A
、B
、C
.
class Record(models.Model):
STATUS_A = 'A'
STATUS_B = 'B'
STATUS_C = 'C'
SOME_STATUSES = (
(STATUS_A, 'Something A'),
(STATUS_B, 'Something B'),
(STATUS_C, 'Something C'),
)
status = models.CharField(
max_length=1,
choices= SOME_STATUSES,
default= STATUS_A,
)
我有一个 DRF ViewSet
负责 returning Record
对象的过滤查询集。
现在我正在过滤由单一状态设置的查询,所以我的 URL
看起来像:
.../?status=A
.../?status=B
.../?status=C
但是说我想按多种状态过滤查询集:
Return 状态为 A
和 B
的所有记录。
或者我想 return 除了状态为 C
的所有记录。我不确定在这些情况下如何构建 URL。我知道在 URL 中复制参数是一种非常糟糕的做法:
.../?status=A&status=B
如何请求A
AND
B
或NOT
C
?
如何处理这些多个值的问题的其余部分不清楚,可能是因为我一开始就不明白如何构建这样的查询。
通过编写 CustomDjangoFilter,您可以实现这一点。
示例代码
URL 示例和用法
URL : localhost:8000/records/?status_include=A,B
URL : localhost:8000/records/?status_exclude=A
URL : localhost:8000/records/?status_include=A,B,C&status_exclude=D,E,F
代码段
views.py
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CustomRecordFilter
class RecordViewSet(viewsets.ModelViewSet):
queryset = Record.objects.all()
serializer_class = RecordSerializer
# django-filter-backend and custom-filter-class
filter_backends = (DjangoFilterBackend, )
filter_class = CustomRecordFilter
filters.py
import django_filters
class CustomRecordFilter(django_filters.FilterSet):
status_exclude = django_filters.CharFilter(field_name='status', method='filter_status_exclude')
status_include = django_filters.CharFilter(field_name='status', method='filter_status_include')
def filter_status_include(self, queryset, name, value):
if not value:
return queryset
values = ''.join(value.split(' ')).split(',')
queryset = queryset.filter(status__in=values)
return queryset
def filter_status_exclude(self, queryset, name, value):
if not value:
return queryset
values = ''.join(value.split(' ')).split(',')
# exclude status
queryset = queryset.exclude(status__in=values)
return queryset
class Meta:
model = UserRoleGroup
fields = ('status', 'status_include', 'status_exclude')
我想通过同一字段多次过滤 Django 查询集,使用 Q
到 include/exclude 此字段中具有特定值的记录。
我将使用示例模型来说明我的情况。假设我有一个带有字段 status
的 Record
模型。该字段可以是三种状态之一 A
、B
、C
.
class Record(models.Model):
STATUS_A = 'A'
STATUS_B = 'B'
STATUS_C = 'C'
SOME_STATUSES = (
(STATUS_A, 'Something A'),
(STATUS_B, 'Something B'),
(STATUS_C, 'Something C'),
)
status = models.CharField(
max_length=1,
choices= SOME_STATUSES,
default= STATUS_A,
)
我有一个 DRF ViewSet
负责 returning Record
对象的过滤查询集。
现在我正在过滤由单一状态设置的查询,所以我的 URL
看起来像:
.../?status=A
.../?status=B
.../?status=C
但是说我想按多种状态过滤查询集:
Return 状态为 A
和 B
的所有记录。
或者我想 return 除了状态为 C
的所有记录。我不确定在这些情况下如何构建 URL。我知道在 URL 中复制参数是一种非常糟糕的做法:
.../?status=A&status=B
如何请求A
AND
B
或NOT
C
?
如何处理这些多个值的问题的其余部分不清楚,可能是因为我一开始就不明白如何构建这样的查询。
通过编写 CustomDjangoFilter,您可以实现这一点。
示例代码
URL 示例和用法
URL : localhost:8000/records/?status_include=A,B
URL : localhost:8000/records/?status_exclude=A
URL : localhost:8000/records/?status_include=A,B,C&status_exclude=D,E,F
代码段
views.py
from django_filters.rest_framework import DjangoFilterBackend
from .filters import CustomRecordFilter
class RecordViewSet(viewsets.ModelViewSet):
queryset = Record.objects.all()
serializer_class = RecordSerializer
# django-filter-backend and custom-filter-class
filter_backends = (DjangoFilterBackend, )
filter_class = CustomRecordFilter
filters.py
import django_filters
class CustomRecordFilter(django_filters.FilterSet):
status_exclude = django_filters.CharFilter(field_name='status', method='filter_status_exclude')
status_include = django_filters.CharFilter(field_name='status', method='filter_status_include')
def filter_status_include(self, queryset, name, value):
if not value:
return queryset
values = ''.join(value.split(' ')).split(',')
queryset = queryset.filter(status__in=values)
return queryset
def filter_status_exclude(self, queryset, name, value):
if not value:
return queryset
values = ''.join(value.split(' ')).split(',')
# exclude status
queryset = queryset.exclude(status__in=values)
return queryset
class Meta:
model = UserRoleGroup
fields = ('status', 'status_include', 'status_exclude')