8

I am using Django-filter app to construct search on my website. This is the code:

class PropertyFilter(django_filters.FilterSet):
city = django_filters.ModelMultipleChoiceFilter(queryset=City.objects.all(), widget = CheckboxSelectMultiple)
trade_type = django_filters.ModelMultipleChoiceFilter(queryset=Trade.objects.all(), widget = CheckboxSelectMultiple)

class Meta:
    model = Property
    fields = ['city', 'trade_type']

The problem is that when user marks two cities, Django-filter only filters objects via last URL parameter (city no. 2 in this casse):

http://example.org/lt/list/city=1&city=2

Models.py:

class City(models.Model):
    name = models.CharField(max_length=250, verbose_name=_('Name'))

Maybe I am doing something wrong ?

1
  • Perhaps http://example.org/lt/list/?city=1,2 Commented Oct 11, 2014 at 13:43

3 Answers 3

8

You could create a plural version of your query string and accept a list as the filter argument:

http://example.org/lt/list/?cities=1,2


class CustomFilterList(django_filters.Filter):
    def filter(self, qs, value):
        if value not in (None, ''):
            values = [v for v in value.split(',')]
            return qs.filter(**{'%s__%s' % (self.name, self.lookup_type): values})
        return qs

class PropertyFilter(django_filters.FilterSet):
    city = django_filters.ModelMultipleChoiceFilter(queryset=City.objects.all(), widget = CheckboxSelectMultiple)
    trade_type = django_filters.ModelMultipleChoiceFilter(queryset=Trade.objects.all(), widget = CheckboxSelectMultiple)
    cities = CustomFilterList(name="city", lookup_type="in")

    class Meta:
        model = Property
        fields = ['cities', 'city', 'trade_type']

Check out this answer for filtering a list of values properly:

Possible to do an `in` `lookup_type` through the django-filter URL parser?

Sign up to request clarification or add additional context in comments.

Comments

2

You can get it to work with the same URL you were trying. Follow my example. You have to pass the choices that you want to filter with.

The URL that I'm calling:

http://example.org/product-list/gender=1&gender=2

filters.py

GENDER_CHOICES = tuple(
    ProductAttributeOptions.objects.filter(group__name='gender').values_list('id', 'option'))

class ProductFilter(django_filters.FilterSet):        
    gender = django_filters.MultipleChoiceFilter(choices=GENDER_CHOICES,
                                                 method='filter_gender')

    def filter_gender(self, qs, name, value):
        result = qs.filter(Q(attribute_values__attribute__name='gender',
                         attribute_values__value_option__in=value))

        return result

class Meta:
    model = Product
    fields = ('gender')

Hope this could help. I took inspiration from the official docs.

1 Comment

But you have to know GENDER_CHOICES beforehand
1

The best way is to use custom filter from Django filter DOC in my case i used (',') to split the url should look like this:

localhost:8000/?city=1,2,3 (you can use Strings values)

    
   class F(django_filters.FilterSet):
         city = CharFilter(method='my_custom_filter')

         class Meta:
            model = Property
            fields = ['city','trade_type']

         def my_custom_filter(self, queryset, name, value):
            value_list = value.split(u',') #split the values by ,
            return queryset.filter(**{
            name+"__in": value_list, #add __in to get each value of the list
            })

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.