首页 > 解决方案 > 使用 Rest Framework Django API 过滤对象

问题描述

Person在 Django 中有一个模型

class Language(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class Country(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class Person(models.Model):
    PersonId= models.UUIDField(
        primary_key=True, default=uuid.uuid4, editable=False)
    Countries = models.ManyToManyField(Country)
    Languages = models.ManyToManyField(Language)

每个人可以有(访问)许多国家并有(说)多种语言。

我想创建一个 API,我将发送到几个languages和的端点列表countries,并将返回给我的人,他们的列表中至少有我发送的列表中的一种语言和一个国家。

例如我有

Person(1,['Portugal', 'Spain'],['portugues','spanish']),

Person(2, ['Portugal', 'Germany'],['portugues','russian']),

Person(3,['France', 'Spain'],['spanish', 'french'])

我发送数据

{
   Countries: ['Portugal', 'France'],
   Languages: ['russian', 'french']
}

所以在这种情况下它返回Person2and Person3。我的带有身份验证的 PersonView

class PeopleListView(ListAPIView):
    queryset = Person.objects.all()
    serializer_class = PersonSerializer
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]

    def get_queryset(self):
        return Blog.objects.filter(UserId=self.request.user)

有没有办法做到这一点?我不想通过 url 搜索,而是在正文中发送数据。

标签: djangoapidjango-rest-framework

解决方案


如果您要使用 requests 测试下面的答案,它会是什么样子。简单性和使用性是我认为您可以跳过不希望 url 包含过滤器信息的要求的原因。

import requests

requests.get(
    f'http://{site}', 
    params={'Countries': ['Portugal', 'France'], 'Languages': ['russian', 'french']}
).json()

requests 库允许将参数作为字典中的列表发送

需要根据PeopleListView发送的值更新查询集。

class PeopleListView(ListAPIView):
    serializer_class = PersonSerializer
    authentication_classes = [TokenAuthentication, ]
    permission_classes = [IsAuthenticated, ]

    def get_queryset(self):
    """Returns a list of of People that match the critera"""
        # get query parameters
        countries = self.request.GET.getlist('Countries', None)
        languages = self.request.GET.getlist('languages', None)

        # return the filter set based on parameters sent
        if countries is not None and languages is not None:
            return Person.objects.filter(countries__name__in=countries).filter(languages__name__in=languages)
        elif countries is not None and languages is None:
            return Person.objects.filter(countries__name__in=countries)
        elif countries is None and languages is not None:
            return Person.objects.filter(languages__name__in=languages)
        else:
            return Person.objects.all()  # returns everyone if no filters set

这使用The documentation on filtering with Django Rest Framework根据发送的参数更改查询集。

if.. elif... elif... else块使用Django 的 orm 中的过滤文档


推荐阅读