【问题标题】:Filter objects with Rest Framework Django API使用 Rest Framework Django API 过滤对象
【发布时间】:2019-12-04 14:07:47
【问题描述】:

我在 Django 中有一个模型 Person

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']
}

所以在这种情况下它返回Person2 和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 搜索,而是在正文中发送数据。

【问题讨论】:

    标签: django api django-rest-framework


    【解决方案1】:

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

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

    请求库allows for parameters to be sent as a list in a dictionary。

    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 块使用 The documentation on filtering in Django's orm

    【讨论】:

    • 嘿,谢谢或回复。我确实用 POSTMAN 测试了你的回复,你的回答对我帮助很大,但也有一些问题。第一个是我不能发送选项数组,但每个选项都像这样?Countries=France&Countries=Portugal&Languages=russian 分开,然后在 django 中将它们转换为列表countries = self.request.GET.getlist('Countries')。 (https://stackoverflow.com/questions/30106783/django-get-query-parameter-list) 您可以更新您的答案,以便我接受正确的答案。
    • 有道理!我很高兴你能够让它工作!我刚刚更新了答案。是你所期待的吗?
    • 只有您请求中的参数与我写的不匹配 - 它们不能是数组
    • 如果您从 Web 浏览器访问该站点,则需要像 ?Countries=France&Countries=Portugal..etc.. 一样分隔参数。如果您使用requests 库,您可以根据文档将所有内容作为带有嵌入列表的字典发送。我想这也是你所指的。我已经更新了我的答案以包含来自requests 的文档的更多信息。第一部分更多的是关于如何与视图交互的参考,如果它有助于我可以将其全部删除。
    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 2018-01-15
    • 2019-02-12
    • 1970-01-01
    • 2015-09-21
    • 2019-07-11
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多