django-filter(django rest框架)-具有3个参数的方法过滤器

时间:2018-12-14 09:27:08

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

我正在使用django rest框架创建api和django-filter,以为用户提供很好的方式来查看过滤器如何在网站的可浏览api部分中工作。

我需要通过方法调用的结果来过滤查询集。不幸的是,它需要用户提供3个参数(使用lat,lng,radius计算到中心点的距离)。

我知道我可以在filterset中声明一个非模型字段,并带有要调用的方法,但是只有一个参数传递给该方法。 我可以声明3个非模型字段,但是我以3种不同的方法结束,或者用1个更改参数的方法调用同一方法3次。 示例代码:

class PersonFilter(FilterSet):
    status = ChoiceFilter(field_name='status', choices=Person.STATUS_CHOICES)
    # I show an example of what I need to achieve below, obviously it will not work as
    # I need to give the user 3 fields to fill in and call the method only once with their values...

    latitude = NumberFilter(label='latitude', method='check_if_in_range')
    longitude = NumberFilter(label='longitude', method='check_if_in_range')
    radius = NumberFilter(label='radius', method='check_if_in_range') 

    class Meta:
        model = Person
        fields = 'status', 'latitude', 'longitude', 'radius'
example method to filter by 3 parameters:

def check_if_in_range(self, queryset, name, value):
    here I need access to the values from 3 non model form fields...
    do calculation and filter the queryset
        return <filtered queryset>

这甚至可行吗? 我希望我的用户能够使用:

<base_url>?longitude=234234&latitude=232342&radius=34 

通过API过滤人员... 谢谢您的时间和帮助!

Tomasz

1 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

class PersonFilter(FilterSet):
    status = ChoiceFilter(field_name='status', choices=Person.STATUS_CHOICES)
    radius = NumberFilter(label='radius', method='check_if_within_range')

    class Meta:
        model = Person
        fields = 'status', 'radius'

    def check_if_within_range(self, queryset, name, value):
        base_point = Point(latitude=float(self.request.GET.get("latitude")),
                           longitude=float(self.request.GET.get("longitude")))
        return queryset.distance_within(base_point, value)

根据您要如何计算距离和过滤查询集,需要使用自定义方法。在这里,我假设您将在自定义查询集管理器中使用distance_within()方法。

您可以根据需要/结构进行重构。