如何使用 django-filter 的 Filter.method 自定义过滤

How to customize filtering with Filter.method of django-filter

我正在使用 Django 构建一个网站,我正在使用应用程序 django-filter 为我网站的产品构建一个过滤系统。基本上,我网站的所有用户都有一个代表他们当前位置的 localisation 属性(这个属性是来自 GeoDjango 的 PointField)。我希望用户能够过滤位于其位置附近的用户销售的产品。为此,我使用 django_filters 的 method 参数来自定义过滤。我认为我想要做的事情相当简单,但由于 django-filter 文档中缺乏明确的示例,我在实现它时遇到了麻烦。您可以在下面找到我到目前为止尝试过的内容,以及使用的模型,以便您了解我所做的事情。

模型之间的关系结构有点复杂,但我认为您不需要它来理解我的问题。以下是该结构的完整解释,以防有用:User 模型链接到 UserAdvanced 模型,为用户提供高级功能。此 UserAdvanced 模型可选择链接到代表可以销售产品的用户的 Chef 模型。最后,Chef 模型可以链接到代表用户销售的产品的 Plat 模型。我想根据 UserAdvanced 模型的 localisation 属性过滤 Plat 产品。

models.py(仅相关部分)

class UserAdvanced(models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE)
    localisation = models.PointField(blank = True, null = True)

class Chef(models.Model):
    userAdv = models.OneToOneField(UserAdvanced, on_delete = models.CASCADE)

class Plat(models.Model):
    chef = models.ForeignKey(Chef, on_delete = models.CASCADE)

filters.py

class PlatFilter(django_filters.FilterSet):
    titre = django_filters.CharFilter(
        field_name='titre', label='Mot clé :', lookup_expr='icontains',
        widget=forms.TextInput(attrs={'class': 'form-control'}),
    )

    distance = django_filters.NumberFilter(
        method='distance_filter', label='Distance maximum en mètres de votre position (n\'oubliez pas de la mettre à jour si nécessaire)',
        widget=forms.NumberInput(attrs={'class': 'form-control'}),
    )

    class Meta:
        model = Plat
        fields = ['titre', 'nb_portions', 'date_prep']

    def distance_filter(self, queryset, name, value):
        return queryset.filter(chef__useradvanced__localisation.distance(request__user__useradvanced__localisation)__lte = value)

我正在使用 GeoDjango 的距离函数计算两点之间的距离,并且我正在尝试过滤查询集以获取此距离小于或等于提供的值的产品。目前,我有 SyntaxError: invalid syntax。就像我说的,我认为解决方案相当简单,但由于互联网上缺乏文档,我很难找到它。如果能提供一点帮助,我们将不胜感激。

提前致谢!

你的问题在最后一行

def distance_filter(self, queryset, name, value):
    return queryset.filter(chef__useradvanced__localisation.distance(request__user__useradvanced__localisation)__lte = value)
    #                                                                                                          ^here

__lte处错了