基于Django Rest Framework

时间:2017-10-03 01:17:25

标签: python django django-rest-framework django-filter

我有一个标签数组作为模型字段,我想根据这些数组元素过滤掉。这里是标记字段是我猜的数组类型的模型。

class Mineral(models.Model):
    name=models.CharField(max_length=500)
    tags=TaggableManager()
    def __unicode__(self):
        return self.name

现在在我看来,我想基于此标记字段过滤掉 我可以像这样使用Django这样做

class MineralList(APIView):
    queryset = Mineral.objects.all()
    serializer_class = MineralSerializer

    permission_classes = [AllowAny]

    def get(self, request, format=None):
        mineral = Mineral.objects.all()

        tags = request.query_params.get('tags', None)
        name= request.query_params.get('name',None)

        if tags is not None:
            tags = tags.split(',')
            mineral = mineral.filter(tags__name__in=tags).distinct()
        if name:
            mineral = mineral.filter(name=name)
        serializer = MineralSerializer(mineral, many=True)
        return Response(serializer.data)

如何使用过滤后端和过滤器类

以REST方式执行此操作

2 个答案:

答案 0 :(得分:1)

您可以像这样创建FilterSet类:

from django_filters.rest_framework import FilterSet, filters
from django_filters.widgets import CSVWidget


class MineralFilterSet(FilterSet):
    tags = filters.CharFilter(distinct=True, widget=CSVWidget, method='filter_tags')
    name = filters.CharFilter()

    class Meta:
        model = Mineral
        fields = ['name', 'tags']

    def filter_tags(self, queryset, name, value):
        return queryset.filter(tags__name__in=value)

你的观点应该是这样的:

from django_filters.rest_framework import DjangoFilterBackend

class MineralList(ListAPIView):
    queryset = Mineral.objects.all()
    serializer_class = MineralSerializer

    permission_classes = [AllowAny]

    filter_backends = (DjangoFilterBackend,)
    filter_class = MineralFilterSet

答案 1 :(得分:1)

我很难得到加百利的答案,所以如果其他任何人都面临这个问题,这对我来说很有效。

过滤器:

from django_filters.rest_framework import FilterSet, filters
from django_filters.widgets import CSVWidget

from .models import Contact


class ContactFilter(FilterSet):
    tags = filters.BaseCSVFilter(
        distinct=True, widget=CSVWidget(), method="filter_tags"
    )

    class Meta:
        model = Contact
        
    @staticmethod
    def filter_tags(queryset, field_name, value):
        return queryset.filter(tags__name__in=value)

ViewSet:

from django_filters.rest_framework import DjangoFilterBackend

class ContactViewSet(ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = ContactFilter

重要的部分是使用BaseCSVFilter而不是CharFilter,否则CSVWidget将吐出列表的字符串,而不是列表。