【问题标题】:django rest framework return a custom object using ModelSerializer and ModelViewSetdjango rest 框架使用 ModelSerializer 和 ModelViewSet 返回一个自定义对象
【发布时间】:2018-01-18 21:03:50
【问题描述】:

我有三个模型,三个序列化器,一个模型视图集。 我正在使用 django-rest-framework 为 android 制作一个 rest api。

首先创建了餐厅模型。然后我创建了一个星形模型和一个图像模型。

我想做的是将星星和图像对象添加到餐厅对象中。

我终于得到了我想要的结果,但我认为我的视图集代码看起来有问题..

还有其他不使用“for循环”的方法吗?

型号

class Restaurant(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)
    address = models.CharField(max_length=255)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    weather = models.ForeignKey(Weather, on_delete=models.CASCADE)
    distance = models.ForeignKey(Distance, on_delete=models.CASCADE)
    description = models.TextField('DESCRIPTION')

    def __str__(self):
        return self.name

class Star(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    rating = models.IntegerField('RATING')

    def __str__(self):
        return self.restaurant


class RestaurantImage(models.Model):
    id = models.AutoField(primary_key=True)
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    path = models.CharField(max_length=255)

序列化器

class StarSerializer(serializers.ModelSerializer):
    class Meta:
        model = Star
        fields = ('id', 'restaurant', 'user', 'rating', )


class RestaurantDetailSerializer(serializers.ModelSerializer):
    category = CategorySerializer()
    weather = WeatherSerializer()
    distance = DistanceSerializer()

    class Meta:
        model = Restaurant
        fields = ('id', 'name', 'address', 'category', 'weather',
                  'distance', 'description', )


class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = RestaurantImage
        fields = ('id', 'path', 'restaurant')

视图集

class RestaurantDetailInfoViewSet(viewsets.ModelViewSet):
    queryset = Restaurant.objects.all()
    serializer_class = RestaurantSerializer

    def list(self, request, *args, **kwargs):
        restaurant_list = Restaurant.objects.all()
        restaurant_result = []
        for restaurant in restaurant_list:
            restaurantInfo = Restaurant.objects.filter(id=restaurant.pk)
            restaurant_serializer = RestaurantDetailSerializer(restaurantInfo, many=True)
            ratingAverageValue = Star.objects.filter(restaurant=restaurant.pk).aggregate(Avg('rating'))
            images = RestaurantImage.objects.filter(restaurant=restaurant.pk)
            image_serializer = ImageSerializer(images, many=True)

            restaurant_dic = {
                'restaurant': restaurant_serializer.data,
                'ratingAverage': ratingAverageValue['rating__avg']
                if ratingAverageValue['rating__avg'] is not None else 0,
                'images': image_serializer.data
            }
            restaurant_result.append(restaurant_dic)

        return Response(restaurant_result)

结果

[
{
    "restaurant": [
        {
            "id": 1,
            "name": "restaurant1",
            "address": "address1",
            "category": {
                "c_id": 1,
                "name": "foodtype1"
            },
            "weather": {
                "w_id": 1,
                "name": "sunny"
            },
            "distance": {
                "d_id": 1,
                "name": "inside"
            },
            "description": "description1"
        }
    ],
    "ratingAverage": 2.6667,
    "images": [
        {
            "id": 1,
            "path": "imagepath",
            "restaurant": 1
        }
    ]
},

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    解决方案

    class RestaurantDetailSerializer(serializers.ModelSerializer):
        category = CategorySerializer()
        weather = WeatherSerializer()
        distance = DistanceSerializer()
    
        images = ImageSerializer(many=True, read_only=True)
        ratingAverage = serializers.SerializerMethodField(read_only=True)
    
        def get_ratingAverage(self, restaurant):
            ratingAvgVal = Star.objects.filter(
                             restaurant=restaurant
                           ).aggregate(Avg('rating'))['rating__avg']
            return ratingAvgVal if ratingAvgVal is not None else 0
    
        class Meta:
            model = Restaurant
            fields = ('id', 'name', 'address', 'category', 'weather',
                      'distance', 'description', 'images', 'ratingAverage', )
    

    解释

    在这里,我将ImageSerializer 嵌套在RestaurantSerializer 类中,因为您需要在ImageSerializer 中定义的所有字段。
    然后,对于ratingAverage,我使用了SerializerMethodField,它返回在我为它定义的方法中计算的值(你的逻辑),即get_ratingAverage,它将Restaurant实例引用作为参数传递到字段的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 2021-01-26
      • 2019-03-24
      • 2016-06-01
      • 2017-03-01
      • 1970-01-01
      相关资源
      最近更新 更多