【问题标题】:Django rest filter by serializermethodfield with custom filterDjango rest 通过带有自定义过滤器的 serializermethodfield 进行过滤
【发布时间】:2022-11-18 09:40:27
【问题描述】:

如问题标题中所述,我的任务是按模型中未显示但由序列化程序计算的字段过滤结果。

下面是查看代码:

class RecipeViewSet(ModelViewSet):
    queryset = Recipe.objects.all()
    permission_classes = [IsAdminOrAuthorOrReadOnly, ]
    serializer_class = RecipeInSerializer
    pagination_class = LimitPageNumberPagination
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['tags', ]
    filter_class = RecipeFilter

序列化器:

class RecipeOutSerializer(serializers.ModelSerializer):
    tags = ManyRelatedField(child_relation=TagSerializer())
    author = CustomUserSerializer()
    ingredients = serializers.SerializerMethodField()
    is_favorite = serializers.SerializerMethodField()
    is_in_shopping_cart = serializers.SerializerMethodField()

    class Meta:
        fields = '__all__'
        model = Recipe

    def get_ingredients(self, obj):
        ingredients = IngredientAmount.objects.filter(recipe=obj)
        return GetIngredientSerializer(ingredients, many=True).data

    def get_is_favorite(self, obj):
        request = self.context.get("request")
        if request.user.is_anonymous:
            return False
        return Favorite.objects.filter(recipe=obj, user=request.user).exists()

    def get_is_in_shopping_cart(self, obj):
        request = self.context.get("request")
        if not request or request.user.is_anonymous:
            return False
        return ShoppingCart.objects.filter(recipe=obj, user=request.user).exists()

和自定义过滤器代码:

class RecipeFilter(rest_framework.FilterSet):
    tags = ModelMultipleChoiceFilter(
        field_name='tags__slug',
        to_field_name="slug",
        queryset=Tag.objects.all()
    )

    favorite = BooleanFilter(field_name='is_favorite', method='filter_favorite')

    def filter_favorite(self, queryset, name, value):
        return queryset.filter(is_favorite__exact=True)

    class Meta:
        model = Recipe
        fields = ['tags', ]

目标是返回布尔值的 is_favorited 字段。我尝试在返回查询集的自定义过滤器类中编写 func 但没有用,两个文档都没有帮助我提供示例。希望得到您的帮助。

【问题讨论】:

    标签: python django django-rest-framework django-filter


    【解决方案1】:

    我们可以使用queryset注解:

    from django.db import models
    from rest_framework import serializers
    
    class RecipeViewSet(ModelViewSet):
        def get_queryset(self):
            user = self.request.user
            user_id = user.id if not user.is_anonymous else None
            return Recipe.objects.all().annotate(
                total_favorite=models.Count(
                    "favorite",
                    filter=models.Q(favorite__user_id=user_id)
                ),
                is_favorite=models.Case(
                    models.When(total_favorite__gte=1, then=True),
                    default=False,
                    output_field=BooleanField()
                )
            )
    
    
    class RecipeOutSerializer(serializers.ModelSerializer)
        is_favorite = serializers.BooleanField(read_only=True)
    
        class Meta:
            model = Recipe
            fields = (
                # ...
                is_favorite,
            )
    
    class RecipeFilter(rest_framework.FilterSet):
        favorite = BooleanFilter(field_name='is_favorite')
            
    

    【讨论】:

      猜你喜欢
      • 2018-08-18
      • 2021-06-21
      • 1970-01-01
      • 2017-03-09
      • 2016-07-01
      • 2021-02-16
      • 2018-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多