Hisham
Hisham

Reputation: 65

DRF nested-relationships : related_name argument

In DRF documentation:

You'll normally want to ensure that you've set an appropriate related_name argument on the relationship, that you can use as the field name.

If you have not set a related name for the reverse relationship, you'll need to use the automatically generated related name in the fields argument.

My Room model has the following :

hotel = models.ForeignKey(
    Hotel,
    related_name="%(class)s_rooms",
    verbose_name=u'Hotel') 

How to add this to the Hotel serializer? I tried fields = ('room_set', ...) but I get

ImproperlyConfigured at /api/hotel/ Field name room_set is not valid for model Hotel.

Upvotes: 0

Views: 2114

Answers (3)

cezar
cezar

Reputation: 12012

The related name for Hotel in your model class Room resolves as hotel_rooms. If you want to include the relationsship in your serializer class, you can try something like this:

class HotelSerializer(serializers.ModelSerializer):
    # as of the updates based on your comments this may become obsolete
    hotel_rooms = serializers.PrimaryKeyRelatedField(
        many=True,
        read_only=True
    )

    class Meta:
        model = Hotel
        fields = ('hotel_rooms',) # put all other fields you need
        # add depth for displaying nested contents
        depth = 1

UPDATE:

There is an error in my first sentence. The related_name will not resolve to hotel_rooms, but to room_rooms, assuming the class name is Room. The related_name should be meaningful and in this case hotel_rooms or even just rooms makes perfectly sense. When you have the hotel, you can query the hotel rooms:

hotel = Hotel.objects.get(pk=1)
hotel.hotel_rooms.all() # or hotel.rooms.all()

You didn't reveal the need for the use of %(class)s_rooms. It makes sense to use it in abstract classes that will be inherited from other model classes or when using the ContentType framework, where the actuall class name is not yet known at the time of the declaration of related_name.

Upvotes: 0

JPG
JPG

Reputation: 88499

Use fields = ('modelname_rooms', ...)

Assuming you have a model class as,

class Hotel(models.Model):
    name = models.CharField(max_length=123)


class MyModel(models.Model):
    hotel = models.ForeignKey(Hotel, related_name="%(class)s_rooms", verbose_name=u'Hotel')

and in your HotelSerializer,

class HotelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Hotel
        fields = ("mymodel_rooms",)

That is you have to add a prefix to _room to use the related_field. Here the prefix is the name of the model class in lower case letters.

Upvotes: 1

Arghya Saha
Arghya Saha

Reputation: 5713

Too large for comment. But could you check the related_name seems like there is issue with the format, unless you put it intentionally.

hotel = models.ForeignKey(
    Hotel,
    related_name="abcs_rooms", # update this line
    verbose_name=u'Hotel') 

Upvotes: 0

Related Questions