Как фильтровать в Django Rest Framework представление на основе функций?

Сколько документации по фильтрации в Django rest framework, но все примеры относятся к представлению на основе классов, но я пытаюсь сделать то же самое в представлении на основе функций DRF. Я хотел сделать множественный фильтр для моего набора элементов.

Я попробовал один способ и он работает отлично. Сначала я пытаюсь искать по названию товара или ресторана в одном запросе. Затем я беру другое ключевое слово и пытаюсь отфильтровать название ресторана или название товара на основе города ресторана. Все работает отлично, например, если я нажму на этот url http://localhost:8000/api/items/?keyword=lasagne&keyword1=paris

то он дает мне идеальный ответ. Но я спрашиваю о том, что сейчас мой код ищет эту конкретную часть беспорядочно, и я хочу добавить больше полей для множественной фильтрации. Какой процедуре следовать? Должен ли я следовать этой и нескольким запросам и пытаться фильтровать из этого.

Предположим, теперь я хочу отфильтровать набор запросов на основе типа_блюда, цены, типа_предмета, местоположения и затем искать предметы по названию или рестораны по названию

#это мои модели

class Restaurant(models.Model):
    user = models.OneToOneField(CustomUser, related_name='restaurant', on_delete=models.CASCADE, null=False)
    name = models.CharField(max_length=200, blank=True, null=True)
    profile_picture = models.ImageField(null=True, blank=True)
    address = models.TextField(max_length=2000, blank=True, null=True)
    city = models.CharField(max_length=200)
    latitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
    longitude = models.DecimalField(max_digits = 13, decimal_places = 7, blank=True, null=True)
    is_verified = models.BooleanField(default=False)
    createdAt = models.DateTimeField(auto_now_add=True)


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



class Item(models.Model):
    user = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    name = models.CharField(max_length=220)
    image = models.ImageField(null=True, blank=True)
    dish_type = models.ForeignKey(Dishtype, on_delete=models.CASCADE)
    item_type = models.ForeignKey(Itemtype, on_delete=models.CASCADE)
    description = models.TextField(max_length=10000)
    rating = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
    numReviews = models.IntegerField(null=True, blank=True, default=0)
    old_price = models.DecimalField(max_digits=11, decimal_places=2)
    discount = models.IntegerField(blank=True, null=True)
    price = models.DecimalField(max_digits=12, decimal_places=2, blank=True, null=True)
    countInStock = models.IntegerField(blank=True, null=True, default=0)
    createdAt = models.DateTimeField(auto_now_add=True)
    _id = models.AutoField(primary_key=True, editable=False)
    

    def save(self, *args, **kwargs):
        self.price = Decimal(self.old_price * (100 - self.discount) / 100)
        return super(Item, self).save(*args, **kwargs)
    

    class Meta:
        ordering = ['-createdAt']


    def __str__(self):
        return self.name

#serializer

class RestaurantSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField(read_only=True)
    
    class Meta:
        model = Restaurant
        fields = '__all__'

    
    def get_user(self, obj):
        user = obj.user
        serializer = UserSerializer(user, many=False)
        return serializer.data



class ItemSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField(read_only=True)
    dish_type = serializers.SerializerMethodField(read_only=True)
    item_type = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Item
        fields = '__all__'

    def get_user(self, obj):
        user = obj.user
        serializer = RestaurantSerializer(user, many=False)
        return serializer.data

    def get_dish_type(self, obj):
        dish_type = obj.dish_type
        serializer = DishtypeSerializer(dish_type, many=False)
        return serializer.data

    def get_item_type(self, obj):
        item_type = obj.item_type
        serializer = ItemtypeSerializer(item_type, many=False)
        return serializer.data

#views.py

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getItems(request):
    user = request.user
    
    query = request.query_params.get('keyword')
    if query == None:
        query = ''

    cuery = request.query_params.get('keyword1')
    if cuery == None:
        cuery = ''
        items = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all().filter(
                    Q(name__icontains = query) | Q(user__name__icontains = query))
    else:
        restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related('item_type').all(
                            ).filter(Q(user__city__iexact = cuery))
        
        items = restaurant_city.filter(Q(name__icontains = query) | Q(user__name__icontains = query))


    serializer = ItemSerializer(items, many=True)
    return Response(serializer.data)

Вы можете использовать queryset и переопределить get_queryset функцию.

class FooViewSet(GenericViewSet, mixins.ListModelMixin):
    authentication_classes = [JSONWebTokenAuthentication]
    permission_classes = [IsAuthenticated]
    serializer_class = ItemSerializer
    def get_queryset(self):
        query = self.request.query_params.get('keyword', '')
        if not self.request.query_params.get('keyword1'):
            items = Item.objects.select_related('user').select_related('dish_type').select_related(
                'item_type').all().filter(
                Q(name__icontains=query) | Q(user__name__icontains=query))
        else:
            restaurant_city = Item.objects.select_related('user').select_related('dish_type').select_related(
                'item_type').all(
            ).filter(Q(user__city__iexact=self.request.query_params.get('keyword1', '')))
    
            items = restaurant_city.filter(Q(name__icontains=query) | Q(user__name__icontains=query))
        return items

Вернуться на верх