Django REST Framework ManyToMany 过滤多个值
Django REST Framework ManyToMany filter multiple values
我有两个模型,一个定义用户,另一个定义这些用户的标签。我正在使用 Django REST Framework 创建一个 API。我希望能够查询至少包含标签 ID 1 和 2 的用户。
例如,如果用户的标签是:
[(1,2), (1,2,3), (2,3), (1,3)]
我希望查询 return
[(1,2), (1,2,3)]
.
到目前为止,我已经设法通过以下方式查询具有给定标签(假设 id=1)的用户:/api/users/?labels=1
,但我无法查询具有标签 1 和 2 的用户。我'我试过 /api/users/?labels=1,2
或 /api/users/?labels=1&labels=2
但它 return 一些无效用户,即没有标签 1 或 2 的用户...
Github 测试回购:
https://github.com/TheDimLebowski/drf-m2m-filter
代码:
models.py
class Label(models.Model):
name = models.CharField(max_length = 60)
class User(models.Model):
labels = models.ManyToManyField(Label)
filters.py
class UserFilter(django_filters.FilterSet):
labels = django_filters.filters.BaseInFilter(
name='labels',
lookup_type='in',
)
class Meta:
model = User
fields = ('labels',)
serializers.py
class LabelSerializer(serializers.ModelSerializer):
class Meta:
model = Label
fields = ('id','name')
class UserSerializer(serializers.ModelSerializer):
labels = LabelSerializer(many = True)
class Meta:
model = User
fields = ('labels',)
views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_class = UserFilter
filter_fields = ('labels',)
您可以链接过滤器。例如,如果您需要所有标签包含 1
和 2
值的用户,您可以编写如下查询:
User.objects.filter(labels=1).filter(labels=2)
django-filters
默认情况下不支持这样的查询,因此您需要自定义过滤器。
class M2MFilter(django_filters.Filter):
def filter(self, qs, value):
if not value:
return qs
values = value.split(',')
for v in values:
qs = qs.filter(labels=v)
return qs
class UserFilter(django_filters.FilterSet):
labels = M2MFilter(name='labels')
class Meta:
model = User
fields = ('labels',)
现在您可以编写标签 ID 的逗号分隔并准确获取您需要的内容
/api/users/?labels=1,2
Here is good answer about m2m queries
使用 UserViewSet
中的链接过滤器如下:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
def get_queryset(self):
queryset = User.objects.all()
labels = eval(self.request.query_params.get('labels', []))
for label in labels:
queryset = queryset.filter(labels__in=[label])
return queryset
并像这样查询:
/api/users/?labels=[1,2]
似乎有效!
我有同样的问题,我发现了这样的东西:
from django.db.models import Q
from rest_framework import viewsets
class YourViewSet(viewsets.ModelViewSet)
def get_queryset(self):
# get lable infos here
lables_info = self.request.query_params.get('lable')
lables = lables_info.split(',')
lable1, lable2 = lables[0], lables[1]
return models.objects.fliter(
Q(lable=lable1) | Q(lable=lable2)
)
.......
Django==2.2.4
djangorestframework==3.10.2
django-filter==2.2.0
我有两个模型,一个定义用户,另一个定义这些用户的标签。我正在使用 Django REST Framework 创建一个 API。我希望能够查询至少包含标签 ID 1 和 2 的用户。
例如,如果用户的标签是:
[(1,2), (1,2,3), (2,3), (1,3)]
我希望查询 return
[(1,2), (1,2,3)]
.
到目前为止,我已经设法通过以下方式查询具有给定标签(假设 id=1)的用户:/api/users/?labels=1
,但我无法查询具有标签 1 和 2 的用户。我'我试过 /api/users/?labels=1,2
或 /api/users/?labels=1&labels=2
但它 return 一些无效用户,即没有标签 1 或 2 的用户...
Github 测试回购:
https://github.com/TheDimLebowski/drf-m2m-filter
代码:
models.py
class Label(models.Model):
name = models.CharField(max_length = 60)
class User(models.Model):
labels = models.ManyToManyField(Label)
filters.py
class UserFilter(django_filters.FilterSet):
labels = django_filters.filters.BaseInFilter(
name='labels',
lookup_type='in',
)
class Meta:
model = User
fields = ('labels',)
serializers.py
class LabelSerializer(serializers.ModelSerializer):
class Meta:
model = Label
fields = ('id','name')
class UserSerializer(serializers.ModelSerializer):
labels = LabelSerializer(many = True)
class Meta:
model = User
fields = ('labels',)
views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
filter_class = UserFilter
filter_fields = ('labels',)
您可以链接过滤器。例如,如果您需要所有标签包含 1
和 2
值的用户,您可以编写如下查询:
User.objects.filter(labels=1).filter(labels=2)
django-filters
默认情况下不支持这样的查询,因此您需要自定义过滤器。
class M2MFilter(django_filters.Filter):
def filter(self, qs, value):
if not value:
return qs
values = value.split(',')
for v in values:
qs = qs.filter(labels=v)
return qs
class UserFilter(django_filters.FilterSet):
labels = M2MFilter(name='labels')
class Meta:
model = User
fields = ('labels',)
现在您可以编写标签 ID 的逗号分隔并准确获取您需要的内容
/api/users/?labels=1,2
Here is good answer about m2m queries
使用 UserViewSet
中的链接过滤器如下:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
def get_queryset(self):
queryset = User.objects.all()
labels = eval(self.request.query_params.get('labels', []))
for label in labels:
queryset = queryset.filter(labels__in=[label])
return queryset
并像这样查询:
/api/users/?labels=[1,2]
似乎有效!
我有同样的问题,我发现了这样的东西:
from django.db.models import Q
from rest_framework import viewsets
class YourViewSet(viewsets.ModelViewSet)
def get_queryset(self):
# get lable infos here
lables_info = self.request.query_params.get('lable')
lables = lables_info.split(',')
lable1, lable2 = lables[0], lables[1]
return models.objects.fliter(
Q(lable=lable1) | Q(lable=lable2)
)
.......
Django==2.2.4
djangorestframework==3.10.2
django-filter==2.2.0