django-фильтр (django rest framework) - метод фильтра с 3 параметрами - PullRequest
0 голосов
/ 14 декабря 2018

Я использую django rest Framework для создания API и django-фильтра, чтобы предоставить пользователям хороший способ увидеть, как работают фильтры в доступной для навигации части API сайта.

Мне нужно отфильтроватьqueryset в результате вызова метода.К сожалению, пользователю необходимо предоставить 3 параметра (вычислить расстояние от центральной точки, используя широта, lng, радиус).

Я знаю, что могу объявить поле не модели в наборе фильтров с методом для вызова, но затемтолько один параметр передается методу.Я могу объявить 3 поля, не являющихся моделями, но затем я заканчиваю 3 разными методами или вызываю один и тот же с 3 изменяющимися параметрами 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 ... Спасибо за ваше время и помощь!

Томаш

1 Ответ

0 голосов
/ 14 декабря 2018

Вы можете сделать что-то вроде этого:

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() метод в вашем собственном менеджере наборов запросов.

Вы можете выполнить рефакторинг в соответствии с вашими потребностями / структурой.

...