在DRF 3.0中的响应输出中添加额外的字段

时间:2020-06-15 15:14:21

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

我有以下型号

class Restaurant(models.Model):
    name_of_the_restaurant = models.CharField(max_length=30, blank=True)
    opening_time = models.TimeField(auto_now=False, auto_now_add=False)
    closing_time = models.TimeField(auto_now=False, auto_now_add=False)

还有

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    city = models.CharField(max_length=30, blank=True)
    country = models.CharField(max_length=30, blank=True)
    postal_code = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)
    favourite_restaurant = models.ManyToManyField(Restaurant,
                                                  blank=True,
                                                  related_name='favourite_restaurant',
                                                  related_query_name='favourite_restaurant')

我为餐厅模型定义了一个序列化器,主要是:

class RestaurantSerializer(serializers.ModelSerializer):

    class Meta:
        model = Restaurant
        fields = '__all__'

现在,在ViewSet逻辑中,我正在执行以下操作:

class RestaurantListView(generics.ListAPIView):
    serializer_class = RestaurantSerializer

    def get_queryset(self):
        queryset = {'Error': 'Please pass valid url parameters'}
        city = self.request.query_params.get('city', None)
        postal_code = self.request.query_params.get('postalcode', None)
        country = self.request.query_params.get('country', None)
        if city is not None or postal_code is not None:
            queryset = Restaurant.objects.filter(
                Q(city=city) | Q(pincode=postal_code))
        if country and city is not None and postal_code is None:
            queryset = Restaurant.objects.filter(country=country, city=city)
        return queryset

    def get(self, request, format=None):
        restaurant_qs = self.get_queryset()
        ids_list = [restaurant.id for restaurant in restaurant_qs]
        favourite_restaurant = is_favourite_restaurant(ids_list, self.request.user)
        serializer = RestaurantSerializer(restaurant_qs, many=True)
        return Response(serializer.data)

其中is_favourite_restaurant是一个自定义函数函数,它返回用户最喜欢的餐厅的查询集。现在,在此GET请求的输出中,我得到的结果是:

[
    {
        "id": 2,
        "name_of_the_restaurant": "Aniket",
        "opening_time": "14:08:33.413402",
        "closing_time": "22:08:33.413414"
    },
    {
        "id": 3,
        "name_of_the_restaurant": "Aniket-1",
        "opening_time": "14:13:37.656385",
        "closing_time": "22:13:37.656397"
    }
]

我想要的输出是将额外字段is_favourite:true附加到该用户先前已标记为收藏的餐厅。因此输出应为

[
    {
        "id": 2,
        "name_of_the_restaurant": "Aniket",
        "opening_time": "14:08:33.413402",
        "closing_time": "22:08:33.413414",
        "is_favourite": true, 
    },
    {
        "id": 3,
        "name_of_the_restaurant": "Aniket-1",
        "opening_time": "14:13:37.656385",
        "closing_time": "22:13:37.656397"
    }
]

编辑:

is_favourite_restaurant函数的定义:

def is_favourite_restaurant(restaurant_qs, user):
    favourite_restaurant_qs = Profile.objects.get(user=user).favourite_restaurant.filter(
        pk__in=restaurant_qs.values_list('id', flat=True))
    return favourite_restaurant_qs

1 个答案:

答案 0 :(得分:1)

您可以使用SerializerMethodField。 SerializerMethodField允许添加额外的字段,该字段只能根据需要读取。

class RestaurantSerializer(serializers.ModelSerializer):
    is_favorite = serializers.SerializerMethodField()

    class Meta:
        model = Restaurant
        fields = ('your', 'fields', 'is_favorite')

    def get_is_like(self, obj):
        return is_favourite_restaurant(obj.id, self.context['request'].user)

通常,ListAPIView将上下文添加到序列化程序。使用创建方法时,应手动添加。

serializer = RestaurantSerializer(restaurant_qs, many=True, context={'request': self.request})

上下文允许访问一些我们从视图发送的数据。
因为您没有显示is_favourite_restaurant,所以我不能说您应该在该函数中做什么。我想您应该将ids参数从数组更改为一个id。

您的回复看起来像

[
    {
        "id": 2,
        "name_of_the_restaurant": "Aniket",
        "opening_time": "14:08:33.413402",
        "closing_time": "22:08:33.413414",
        "is_favourite": True, 
    },
    {
        "id": 3,
        "name_of_the_restaurant": "Aniket-1",
        "opening_time": "14:13:37.656385",
        "closing_time": "22:13:37.656397",
        "is_favourite": False, 

    }
]

def is_favourite_restaurant(restaurant_id, user):
    favourite_restaurant_qs = Profile.objects.get(user=user).favourite_restaurant.filter(
        pk=restaurant_id).exists()
    return favourite_restaurant_qs