joe
joe

Reputation: 9503

DRF Search on ArrayField

Specifications:
django==1.11.5
djangorestframework==3.6.4
PostgreSQL 9.6.5 on x86_64-apple-darwin14.5.0, compiled by Apple LLVM version 7.0.0 (clang-700.1.76), 64-bit
Python 3.6.2

models.py

from django.contrib.postgres.fields import ArrayField
from django.db import models
from djchoices import DjangoChoices, ChoiceItem


class Customer(models.Model):
    ...
    phones = ArrayField(models.CharField(max_length=30))

filters.py

import django_filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import FilterSet
from rest_framework.viewsets import ModelViewSet

from soken_web.apps.customers.api.serializers import CustomerSerializer
from soken_web.apps.customers.models import Customer


class CharInFilter(django_filters.BaseInFilter, django_filters.CharFilter):
    pass


class CustomerFilter(FilterSet):
    phones = CharInFilter(name='phones', lookup_expr='contains')

    class Meta:
        model = Customer
        fields = (
            ...,
            'phones',
        )


class CustomerViewset(ModelViewSet):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_class = CustomerFilter
    filter_fields = (
        ...
        'phones',
    )

References: https://groups.google.com/forum/#!topic/django-filter/ns7zx1C8HN8

AS IS: I have to search the exact match phone number of that customer.
For example customer.phones = ['024382426', '024387269']
I have to filter with 024382426 to get that customers.

Question: How to do put the phone number in short like 438 and get that customer?

Upvotes: 2

Views: 2130

Answers (1)

Prakhar Trivedi
Prakhar Trivedi

Reputation: 8526

ArrayField is actually a list. And for list lookup, in keyword is used. You are using contains, and that is for CharField. You need to put in as the lookup_expr like this :

import django_filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import FilterSet
from rest_framework.viewsets import ModelViewSet

from soken_web.apps.customers.api.serializers import CustomerSerializer
from soken_web.apps.customers.models import Customer


class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
    pass


class CustomerFilter(FilterSet):
    phones = NumberInFilter(name='phones', lookup_expr='in')

    class Meta:
        model = Customer
        fields = (
            ...,
            'phones',
        )


class CustomerViewset(ModelViewSet):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_class = CustomerFilter
    filter_fields = (
        ...
        'phones',
    )

And for Arrayfield, you need NumberFilter in the place of CharFilter. Updated this also, Please check.

Upvotes: 2

Related Questions