Julien Mertz
Julien Mertz

Reputation: 485

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

I'm building a website with Django and I'm using the app django-filter to build a filtering system for the products of my website. Basically, all the users of my website have a localisation attribute that represents their current location (this attribute is a PointField from GeoDjango). I would like the user to be able to filter products sold by users located near its location. To do that, I'm using the method argument of django_filters to customize the filtering. I think what I want is rather simple to do but I'm in trouble implementing it due to the lack of explicit examples on the documentation of django-filter. You can find below what I have tried so far, with the models used so you can understand what I did.

The relationship structure between the models is a bit complicated but I don't think you need it to understand my question. Here is the complete explanation of the structure in case it's useful: the User model is linked to a UserAdvanced model providing advanced features for the user. This UserAdvanced model is optionnaly linked to a Chef model that represents the users that can sold products. Finally, the Chef model can be linked to a Plat model that represents the products sold by the user. I want to filter the Plat product based on the localisation attribute of the UserAdvanced model.

models.py (relevant parts only)

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)

I'm computing the distance between the 2 points using the distance function of GeoDjango and I'm trying to filter the queryset to get the products for which this distance is lower or equal to the value provided. Currently, I'm having a SyntaxError: invalid syntax. Like I said, I think the solution is rather simple but I'm having a hard time finding it due to lack of documentation on the internet. A little help would be greatly appreciated.

Thanks in advance !

Upvotes: 0

Views: 2021

Answers (1)

Sardorbek Imomaliev
Sardorbek Imomaliev

Reputation: 15390

Your issue here on the last line

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

__lte at the is wrong

Upvotes: 1

Related Questions