user3521180
user3521180

Reputation: 1130

why the django rest framework's search filter giving errors?

I am working on a demo DRF project to develop search and filter feature. However, I am not able to understand the issue with my project. I have some data stored in DB, and the GET is working fine. However, if I am doing some search operations in POSTMAN, I am seeing error, which is beyond my understanding.

I have followed the below DRF official link. Below is the error

    raise FieldError('Related Field got invalid lookup: {}'.format(lookup_name))
django.core.exceptions.FieldError: Related Field got invalid lookup: icontains
[12/Jan/2021 11:32:53] "GET /api/shop/?search=Amitesh HTTP/1.1" 500 154116

Below are the project details:

models.py

from django.db import models
from django.contrib.auth.base_user import BaseUserManager
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils.translation import gettext_lazy as _


class AccountManager(BaseUserManager):
    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        return self.create_user(email, password, **extra_fields)

    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError(_('Enter the email before proceeding'))

        email = self.normalize_email(email)
        user = self.model(email=email, password=password, **extra_fields)
        user.set_password(password)
        user.save()
        return user


class Shop(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    shop_name = models.CharField(max_length=150)
    contact = models.CharField(max_length=10)
    State = models.CharField(max_length=100)
    district = models.CharField(max_length=100)
    location = models.CharField(max_length=100)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    last_login = models.DateTimeField(null=True)

    objects = AccountManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['shop_name', 'contact', 'is_staff']

    def __str__(self):
        return str(self.shop_name)


class Medicine(models.Model):
    medicine_name = models.ForeignKey(Shop, on_delete=models.CASCADE, max_length=100)
    company = models.CharField(max_length=100)
    salt_power = models.CharField(max_length=100)
    manufacturing_date = models.DateField()
    expiry_date = models.DateField()
    In_Stock = models.BooleanField()
    medicine_Type = models.CharField(max_length=50)
    number_available = models.IntegerField()

    def __str__(self):
        return str(self.medicine_name)

views.py

class ShopRESTView(generics.ListCreateAPIView):
    permission_classes = (permissions.AllowAny, )
    search_fields = ['shop_name', 'State', 'district', 'location', 'aushadhi']
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    queryset = Shop.objects.all()
    serializer_class = ShopSerilizer

serializers.py

from rest_framework import serializers
from .models import Shop, Medicine


class MedicineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Medicine
        fields = '__all__'


class ShopSerilizer(serializers.ModelSerializer):
    aushadhi = MedicineSerializer(many=True)

    class Meta:
        model = Shop
        fields = ['shop_name', 'contact', 'State', 'district', 'location', 'aushadhi']

Google Drive link, just in case anybody would like to re-produce the issue.

All the migrations and the migrate went on with out any issue.

Please suggest

Upvotes: 0

Views: 324

Answers (1)

JPG
JPG

Reputation: 88429

In your case, the aushadhi is a "related name" (reverse relation to Medicine) and can't be searched on that field.

So, change your search_fields to something like,

class ShopRESTView(generics.ListCreateAPIView):
    permission_classes = (permissions.AllowAny,)
    search_fields = [
        'shop_name',
        'State',
        'district',
        'location',
        'aushadhi__company',
        'aushadhi__salt_power',
        'aushadhi__medicine_Type'
        # etc
    ]
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    queryset = Shop.objects.all()
    serializer_class = ShopSerilizer

Upvotes: 1

Related Questions