todel23
todel23

Reputation: 108

How to override related field in django?

Let's say we have such models.

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

I have two views:

class ProductsView(ListAPIView):
    serializer_class = ProductSerializer


class ProductDetailsView(RetrieveAPIView):
    serializer_class = ProductDetailsSerializer

serializers:

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')

I want detailed view to provide all photos in flat array photos, like this [main_photo, ...rest_photos]. In other words, In response to detailed view instead of this:

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

I want to get this:

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

How can I do this with django rest framework? On which level should this logic be implemented? Model, View, Serializer?

I think it should be somewhere here, but not quite sure how should it look.

class ProductDetailsView(RetrieveAPIView):
    serializer_class = ProductDetailsSerializer

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

Upvotes: 0

Views: 316

Answers (1)

shourav
shourav

Reputation: 996

For url of the photos add a __str__ method in ProductPhoto which will return only url of the photo

class ProductPhoto(models.Model):
...

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

and change ProductDetailsSerializer like this

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')

For more relation related documentation for DRF check this

Upvotes: 1

Related Questions