django restframework中的to_representation不适用于自定义serializers.SerializerMethodField

时间:2018-04-06 21:05:35

标签: django django-rest-framework

我对使用自定义字段的自定义结构感到困惑,附上了我的参考实现。如果你看到 do_representation ,你输出的结果不符合预期,任何人都知道为什么会这样?

class ImageSerializer(serializers.ModelSerializer):
    thumb = serializers.ImageField()
    class Meta:
        model = Image
        fields = ('thumb',)

class ProductSerializer(serializers.ModelSerializer):
    def product_url(self,obj):
        request = self.context['request']
        return request.build_absolute_uri(reverse('product', args=(obj.slug,)))

    url = serializers.SerializerMethodField('product_url')
    images = ImageSerializer(many=True)

    class Meta:
        model = Product
        fields = ('url', 'images', 'id')

    def to_representation(self,product):
        raise Exception(product.url) # Not working
        raise Exception(product.images) # Not working
        raise Exception(product.id) # Working

以下是错误消息

'Product' object has no attribute 'url'

注意:但是如果我不用to_representation覆盖那么json响应有url字段

我的解决方法

模型

class Product(models.Model):
    title = models.CharField(max_length=256,null=True,blank=False)

class ProductImage(models.Model):
    product = models.ForeignKey('Product',on_delete=models.CASCADE,null=True,blank=True,related_name='product_images')
    image = models.ImageField(upload_to='product/',null=True)
    thumb = ImageSpecField(source='image', 
                        processors=[ResizeToFill(100, 1100)], 
                        format='JPEG', 
                        options={'quality': 70})                

实际输出

{
   "count":5,
   "next":"http://localhost:8000/api/products/?format=json&page=2",
   "previous":null,
   "results":[
      {
         "id":1,
         "images":[
            {
               "thumb":"http://localhost:8000/media/CACHE/images/product/Product1/fee2eb25a1d7b954632dd377aca39995.jpg"
            },
            {
               "thumb":"http://localhost:8000/media/CACHE/images/product/Product2/a279c5057bb5ee6e06945f98d89cc411.jpg"
            }
         ],
         "url":"http://localhost:8000/product/wooden-furniture/"
      }
   ]
}

预期输出

{
   "count":5,
   "next":"http://localhost:8000/api/products/?format=json&page=2",
   "previous":null,
   "results":[
      {
         "id":1,
         "images":[
               "thumb":"http://localhost:8000/media/CACHE/images/product/Product1/fee2eb25a1d7b954632dd377aca39995.jpg",
               "popup":"http://localhost:8000/media/CACHE/images/product/Product2/a279c5057bb5ee6e06945f98d89cc411.jpg" # Will work on it once I achieve it wil popup
         ],
         "url":"http://localhost:8000/product/wooden-furniture/"
      }
   ]
}

我的自定义结构试用

def to_representation(self,obj):
    return {
        'id': obj.id,
        'images': {
            'thumb': obj.images # May be I have to work to get only first image here
        },
        'url': obj.url
    }

1 个答案:

答案 0 :(得分:0)

当您自己呈现数据时。因此,您必须自己做其他事情。

尝试一下,

class ProductSerializer(serializers.ModelSerializer):
    def product_url(self,obj):
        request = self.context['request']
        return request.build_absolute_uri(reverse('product', args=(obj.slug,)))

    class Meta:
        model = Product
        fields = ('url', 'images', 'id')

    def to_representation(self, product):
        image_objs = ProductImage.objects.filter(product=product)
        images = ImageSerializer(image_objs, many=True)

        return {
            "id": product.id,
            "images" images.data,
            "url": self.product_url(product)
        }