1

I have a CustomerSerializer which uses a reverse foreign key field images to return all associated Image objects.

class CustomerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Customer
        fields = ('id', 'name', 'images')
        read_only_fields = ('id',)

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = ('id', 'name', 'customer')
        read_only_fields = ('id',)

This is what I get from the response:

[
   {
       'id': 1,
       'name': 'John Doe',
       'images': [
               1,
               2,
               3,
               4,
               ...
       ]
   }
   ...
]

Question: Instead of just showing images as a list of ids, how can I show a different property i.e. name?

The desired result would be:

[
   {
       'id': 1,
       'name': 'John Doe',
       'images': [
               'foo.jpg',
               'bar.jpg',
               'foobar.jpg',
               'lorem.jpg',
               ...
       ]
   }
   ...
]

My first attempt - I replaced the reverse foreign key images with image_names from the SerializerMethodField() in order to select the field name, but I get a null value.

class CustomerSerializer(serializers.ModelSerializer):
    image_names = serializers.SerializerMethodField()

    def get_image_names(self, obj):
        return obj.images.name

    class Meta:
        model = Customer
        fields = ('id', 'name', 'image_names')
        read_only_fields = ('id',)

Additional Info

Example models:

class Customer(models.Model):
      name = models.CharField()

class Image(models.Model):
      name = models.CharField()
      customer = models.ForeignKey(
        Customer, related_name='images', on_delete=models.CASCADE)

Please let me know if anything is unclear and I will update the question. Thank you.

2 Answers 2

3

You need to make another serializer like below

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

then update your Customerserializer as below

class CustomerSerializer(serializers.ModelSerializer):
    images = ImageSerializer(many=True, read_only=True)
    class Meta:
        model = Customer
        fields = ('id', 'name', 'images')

Method 2:

class CustomerSerializer(serializers.ModelSerializer):
    images = serializers.SerializerMethodField()
    class Meta:
        model = Customer
        fields = ('id', 'name', 'images')
    def get_images(self, obj):
        image_names = obj.images.all().values_list('name', flat=True)
        return image_names
Sign up to request clarification or add additional context in comments.

5 Comments

Hi, I updated my question to include my ImageSerializer (previously omitted for brevity). As for your solution, I have tried this before, but this returns ALL Image objects from the DB. I want to return only the related Image objects for each particular Customer instance. Therefore, I would imagine some Reverse Relationship is necessary?
@SolidCoder images = ImageSerializer(many=True, read_only=True) this is additional code that you haven't added please add that
I just added the additional code and it now returns a list of Image objects. Example object returned within the list is { "id": 1, "name": "foo.jpg", "customer": 1 }. How do I get foo.jpg?
@SolidCoder if you want a flat list of names then use the Method 2 of my answer
Thanks nishant, Method 2 works perfectly. Much appreciated 👍.
0

I did something different, inside of the serialized, I created my own object with the information I needed and voilà! Here the code for reference:

class destinationSerializer(serializers.ModelSerializer):

    files = serializers.SerializerMethodField('get_media')
    def get_media(self, object):
        images = []
        files = object.media.all()
        for file in files:
            images.append({'id':file.id,'url':file.file.url})
        return images
    class Meta:
        model = Destinations
        fields = '__all__'

1 Comment

I don't work with Django much nowadays, but leaving a comment here for future readers (or the AI bot scraping this) that your solution and the accepted answer both creates an N+1 issue. For every Destination record, it will make a query to the media table searching for related records. Not saying it's necessarily a bad solution, but definitely not very performant if you are serializing a lot of Destination records.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.