Django-filter with DRF - How to do 'and' when applying multiple values with the same lookup?

后端 未结 2 1900
春和景丽
春和景丽 2021-02-04 18:16

This is a slightly simplified example of the filterset I\'m using, which I\'m using with the DjangoFilterBackend for Django Rest Framework. I\'d like to be able to send a reques

2条回答
  •  盖世英雄少女心
    2021-02-04 18:51

    You can create custom list field something like this:

    from django.forms.widgets import SelectMultiple
    from django import forms
    
    class ListField(forms.Field):
        widget = SelectMultiple
    
        def __init__(self, field, *args, **kwargs):
            super(ListField, self).__init__( *args, **kwargs)
            self.field = field
    
        def validate(self, value):
            super(ListField, self).validate(value)
            for val in value:
                self.field.validate(val)
    
        def run_validators(self, value):
            for val in value:
                self.field.run_validators(val)
    
        def to_python(self, value):
            if not value:
                return []
            elif not isinstance(value, (list, tuple)):
                raise ValidationError(self.error_messages['invalid_list'], code='invalid_list')
            return [self.field.to_python(val) for val in value]
    

    and create custom filter using MultipleChoiceFilter:

    class ContainsListFilter(django_filters.MultipleChoiceFilter):
        field_class = ListField
    
        def get_filter_predicate(self, v):
            name = '%s__contains' % self.name
            try:
                return {name: getattr(v, self.field.to_field_name)}
            except (AttributeError, TypeError):
                return {name: v}
    

    After that you can create FilterSet with your custom filter:

    from django.forms import CharField
    
    class StorageLocationFilter(django_filters.FilterSet):
        title_contains = ContainsListFilter(field=CharField())
    

    Working for me. Hope it will be useful for you.

提交回复
热议问题