pythonBeginner
pythonBeginner

Reputation: 791

display foreign key in parent class

I could not show reverse relation in Django Rest Framework. Here in my case, a rent can have multiple images and i want to display all the images of that rent(living room image, kitchen image, bathroom image etc) in /api/v1/rent, i mean in rent resource.

So, how do I fetch these Galleries to display in the Rental resource?

class Rental(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=300, blank=False, null=False)
    phone_number = models.PositiveIntegerField(null=False, blank=False)
    renter = models.CharField(choices=RENTER_CHOICES, max_length=1, default=RENTER_CHOICES[0])

    def __str__(self):
        return self.name

def user_directory_path(instance, filename):
    return 'rent_{0}/{1}'.format(instance.rent.id, filename)

class Gallery(models.Model):
    rent = models.ForeignKey(Rental, related_name="rent")
    image = models.FileField(upload_to=user_directory_path)
    tag = models.CharField(max_length=1, choices=TAGS, null=True, blank=True)

class GallerySerializer(serializers.ModelSerializer):
    rent = serializers.ReadOnlyField()
    class Meta:
        model = Gallery
        fields = ('rent', 'image', 'tag',)

class RentalSerializer(serializers.ModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    # gallery = serializers.SerializerMethodField('get_children')
    #
    # def get_children(self, obj):
    #     print ('obj', obj.gallery_set)
    #     serializer = GallerySerializer(obj.gallery_set.all(), many=True)
    #     return serializer.data
    gallery = GallerySerializer(source='gallery_set',many=True, read_only=True)
    class Meta:
        model = Rental
        fields = ('user', 'name', 'phone_number','gallery',)

Right now i dont get the list of gallery, using both way, one commented way and another source='gallery_set' way.

UPDATE

if i do rent = GallerySerializer(many=True) i get the list of galleries but does it make any sense?

[
    {
        "user": "admin",
        "name": "Sunrise Home",
        "phone_number": 9842333833,
        "rent": [
            {
                "image": "http://localhost:8000/media/rent_1/sittingRoom.jpg",
                "tag": "L"
            }
        ]
    }
]

in above api you see the galleries are shown but the name shows it as a list of rent inside rental resource. Can anyone help me to design an api better way?

Upvotes: 0

Views: 166

Answers (1)

natbob1
natbob1

Reputation: 328

When you specify the foreign key relationship for Rental in your Gallery model the related_name you specify automatically defines a field on the Rental object. The name of that field is whatever you set related_name to, in this case rent.

The important thing to understand here is that the related_name will be attached to the opposite side of the relationship from where the key is declared in your models. Because the related name is going to be a property of a Rental object, a better name for it might be galleries in your example.

Assuming you change the related_name in your models from rental to galleries, you can define your Rental serializer to output a list of associated galleries:

class RentalSerializer(serializers.ModelSerializer):
    user = serializers.ReadOnlyField(source='user.username')
    galleries = GallerySerializer(many=True, read_only=True)
    class Meta:
        model = Rental
        fields = ('user', 'name', 'phone_number','galleries')    

By declaring a GallerySerializer with the same name as the related_name defined in your foreign key relationship, it will automatically find only galleries which are associated with the Rental being serialized.

In another example:

Let's say you have several Eggs in a Basket. We would want to create a many-to-one relationship between Eggs and a Basket and would accomplish this by creating a foreign-key relationship between the two. That would be in the form of storing the ID of the associated Basket for each Egg.

In Django, we would declare that foreign key on the Egg model. This allows us to access the basket that an egg is in via egg.basket. We also want to determine what eggs are in a particular basket. We do that by defining a related_name on the foreign-key field. This tells Django what the field linking the basket to all its contained eggs should be called. Since this field refers to all eggs in a basket, we would call it eggs.

In code:

class Basket(models.Model):
    color = models.CharField()

class Egg(models.Model):
    color = models.CharField()
    basket = models.ForeignKey(Basket, related_name="eggs")

Upvotes: 1

Related Questions