Eat_ Mangos
Eat_ Mangos

Reputation: 269

How to use django filter_fields with ArrayField in DRF

I am using a Postgres ArrayField in my models. I am trying to use django filters but I get an error for them.

AutoFilterSet resolved field 'flavor' with 'exact' lookup to an unrecognized field type ArrayField. Try adding an override to 'Meta.filter_overrides'. See: https://django-filter.readthedocs.io/en/master/ref/filterset.html#customise-filter-generation-with-filter-overrides

Model

class Items(models.Model):
    item = models.CharField(max_length=150, unique=True)
    matches = ArrayField(models.CharField(
        max_length=200), blank=True, default=list)
    category = ArrayField(models.CharField(
        max_length=200), blank=True, default=list)
    flavor = ArrayField(models.CharField(
        max_length=200), blank=True, default=list)
    special = ArrayField(models.CharField(
        max_length=200), blank=True, default=list)
    created_at = models.DateTimeField(auto_now_add=True)

ViewSet

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Items.objects.all()
    serializer_class = CategorySerializer
    filter_fields = ('item', 'category')

Upvotes: 10

Views: 9430

Answers (2)

trybek_4
trybek_4

Reputation: 67

If you want to implement some specific lookups for ArrayField, try this:

from django.contrib.postgres.forms.array import SimpleArrayField
from django_filters.filters import Filter

class ArrayOverlapFilter(Filter):
    field_class = SimpleArrayField

  def __init__(self, *args, **kwargs):
      kwargs.setdefault("lookup_expr", "overlap")
      super().__init__(*args, **kwargs)

When you define in FilterSet you have to specify base_field:

devices = ArrayOverlapFilter(base_field=CharField())

Upvotes: 0

Eat_ Mangos
Eat_ Mangos

Reputation: 269

Well I figured it out, lol. Needed to create a custom filter with lookup_exp='icontains'.

class CategoryFilter(filters.FilterSet):
    category = filters.CharFilter(lookup_expr='icontains')

    class Meta:
        model = Items
        fields = ('item', 'category')
class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Items.objects.all()
    serializer_class = CategorySerializer
    filterset_class = CategoryFilter

Upvotes: 13

Related Questions