如何覆盖django中的相关字段?

How to override related field in django?

假设我们有这样的模型。

class Product(models.Model):
    name = models.CharField(max_length=100)
    # ...
    main_photo = models.ImageField(upload_to='photos/')

class ProductPhoto(models.Model):
    product = models.ForeignKey(Product, related_name='photos', on_delete=models.CASCADE)
    photo = models.ImageField(upload_to='photos/')

    def __str__(self):
        return self.photo.url

我有两种看法:

class ProductsView(ListAPIView):
    serializer_class = ProductSerializer


class ProductDetailsView(RetrieveAPIView):
    serializer_class = ProductDetailsSerializer

序列化程序:

class ProductSerializer(ModelSerializer):
    class Meta:
        model = Product
        fields = ('id', 'name', 'main_photo')


class ProductDetailsSerializer(ModelSerializer):
    photos = StringRelatedField(many=True)

    class Meta:
        model = Product
        fields = ('id', 'name', 'main_photo', 'photos')

我想要详细视图以平面阵列 photos 提供所有照片,像这样 [main_photo, ...rest_photos]。 换一种说法, 回应详细视图而不是这个:

{
    "id": 1,
    "name": "name",
    "main_photo": "/media/photos/main_photo.jpg",
    "photos": [
        "/media/photos/photo1.jpg",
        "/media/photos/photo2.jpg",
        "/media/photos/photo3.jpg"
    ],
}

我想要这个:

{
    "id": 1,
    "name": "name",
    "photos": [
        "/media/photos/main_photo.jpg",
        "/media/photos/photo1.jpg",
        "/media/photos/photo2.jpg",
        "/media/photos/photo3.jpg"
    ],
}

如何使用 django rest 框架执行此操作?这个逻辑应该在哪个层次上实现?模型、视图、序列化程序?

我认为它应该在这里的某个地方,但不太确定它应该是什么样子。

class ProductDetailsView(RetrieveAPIView):
    serializer_class = ProductDetailsSerializer

    def get_queryset(self):
        query_set = Product.objects.all()
        # ...
        return query_set

对于 url 的照片,在 ProductPhoto 中添加一个 __str__ 方法,这将 return 只有 url 的照片

class ProductPhoto(models.Model):
...

    def __str__(self):
        return self.photo.url

并像这样更改 ProductDetailsSerializer

class ProductDetailsSerializer(ModelSerializer):
    photo_list = serializers.SerializerMethodField()

    def get_photo_list(self, obj):
        db_photos = obj.photos.all()
        result = []
        if obj.main_photo:
            result.append(obj.main_photo.url)
        for p in db_photos:
            result.append(p.photo.url)
        return result   


    class Meta:
        model = Product
        fields = ('id', 'name', 'photo_list')

有关 DRF 的更多关系相关文档 check this