简体   繁体   中英

Django-filter multiple URL parameters

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 ?

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?

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 .

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
            })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM