【问题标题】:How to set filter range in backend in filter class in django如何在 django 的过滤器类的后端设置过滤器范围
【发布时间】:2020-01-10 15:51:20
【问题描述】:

我正在使用 DRF 构建一个 REST API。我正在使用 django_filters 过滤结果集。在一个api中,我希望用户发送他的坐标(纬度,经度),并在后端创建一个范围为(纬度+2到纬度-2)并返回结果,我不想从用户那里获取范围字段。所以我可以在后端轻松更改范围。

我在过滤器类中创建了两个范围过滤器,它们工作正常,但 url 看起来像这样:/posts/?latitude_min=22&latitude_max=28&longitude_min=80&longitude_max=84。在这里用户负责决定范围。我希望用户只发送纬度和经度,我决定最大和最小范围。

class PostFilter(django_filters.FilterSet):
    latitude = django_filters.RangeFilter(field_name='latitude')
    longitude = django_filters.RangeFilter()

    class Meta:
        model = Post
        fields = ['latitude', 'longitude', 'country', 'state', 'district', ]

【问题讨论】:

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


    【解决方案1】:

    我认为你可以像这样使用“MethodFilter”:

    from django.db.models import Q
    
    class PostFilter(django_filters.FilterSet):
        latitude = django_filters.MethodFilter(action="filter_latitude")
        longitude = django_filters.MethodFilter(action="filter_longitude")
    
        class Meta:
            model = Post
            fields = ['latitude', 'longitude', 'country', 'state', 'district']
    
        def filter_latitude(self, qs, value):
            try:
                return qs.filter(Q(latitude__gte=value-2)&Q(latitude__lte=value+2))
            except BaseException:
                return qs 
    
        def filter_longitude(self, qs, value):
            try:
                return qs.filter(Q(longitude__gte=value-2)&Q(longitude__lte=value+2))
            except BaseException:
                return qs 
    

    【讨论】:

    • 感谢您的快速回答,MethodFilter 现在已被弃用,取而代之的是 Filter.method (django-filter.readthedocs.io/en/stable/guide/…)
    • 我正在浏览新文档,并尝试实施它。如果它有效,将在某个时候更新你。谢谢
    • 我使用数字过滤器为:latitude = django_filters.NumberFilter(field_name='latitude', method='filter_latitude') 并在 filter_latitude 方法中,我将附加参数名称作为“纬度”传递为 ``` def filter_latitude(self, qs, latitude, value):```
    • 你能告诉我如何在 filter_latitude 方法中使用名称字段吗?
    • 请在此处发布您的过滤器类别并附上链接。我想查看所有课程
    【解决方案2】:

    只需几行代码,您就可以编写一个自定义过滤器字段来执行此操作。它可以让您更灵活地在以后添加验证,或者围绕 lat/lng 的细节添加额外的逻辑。

    class ApproximateNumberFilter(Filter):
        field_class = FloatField  # use django base float validation
    
        def __init__(self, under_over=2, **kwargs):
            super().__init__(**kwargs)
            self._under_over = under_over
    
        def filter(self, qs, value):
            if value in EMPTY_VALUES:
                return qs
    
            return qs.filter(**{
                f"{self.field_name}__gte": value - self._under_over,
                f"{self.field_name}__lte": value + self._under_over,
            })
    

    【讨论】:

    • 我应该在我的过滤器集类中使用这种类型的过滤器来处理纬度和经度吗?我创建了这种类型的过滤器,但它不起作用。像这样:latitude = ApproximateNumberFilter(field_name='latitude', ) 然后我在 meta 的字段中简单地添加了这个,我是否正确地遵循它?
    • 是的,这通常是我会使用的。我没有测试过这个特定的,只是把它写出来,但它是标准模板。请随时发送 PM,我会看看我是否可以帮助您解决为什么它可能不适合您。此外,如果 field_name 与成员名称相同,则无需指定它,因为过滤器元类会为您设置。
    • 好的,经过测试,通过PK过滤我的模型时它工作正常,所以应该没问题。其他事情正在发生。
    猜你喜欢
    • 2018-05-15
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-24
    • 2017-10-26
    • 1970-01-01
    • 2010-12-19
    相关资源
    最近更新 更多