Reputation: 882
The code
I have these models :
class Activity(models.Model):
is_child_friendly = models.BooleanField()
free_wifi = models.BooleanField()
parking_avilable = models.BooleanField()
class RouteOrdering(models.Model):
route_id = models.ForeignKey(Route, on_delete=models.CASCADE)
activity_id = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='tracks')
day = models.IntegerField()
order = models.IntegerField()
class Meta:
ordering = ['order']
And these Serializers:
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
class RouteOrderingSerializer(serializers.ModelSerializer):
class Meta:
model = RouteOrdering
fields = ('id','day','order','route_id','activity_id','tracks')
The problem
I want the RouteOrderingSerializer to return also the activity with the same activity_id. For this I thought I should use nested serializers.
What I've tried
I've tried adding a nested serializer like so:
activity = ActivitySerializer( read_only=True)
But this resulted no output in the endpoint. I know this is not the use case presented in the documentation, and this is probably why its noy working.
Ill be glad to see what code will work to get this done :)
Upvotes: 0
Views: 896
Reputation: 1444
I'm not sure why you got an error when you tried the following code. I assumed it was a bug related to the _id
ending, but everything works fine when I run it.
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
class RouteOrderingSerializer(serializers.ModelSerializer):
activity_id = ActivitySerializer( read_only=True)
class Meta:
model = RouteOrdering
fields = ('id','day','order','route_id','activity_id','tracks')
While you can, I don't recommend using a name ending in _id
for a relation in Django. The issue is that Django internally stores all foreign keys under their <relation_name>_id
. This allows various nice things, such as setting <object>.<relation_name>_id
to an integer id and saving the object vs setting <object>.<relation_name>
to the entire related object (which may require a db lookup to get in the first place). The one place I find this behaviour not intuitive is in serializers, where the default is to represent the relation as "<relation_name>": <id>
instead of "<relation_name>_id": <id>
, though you can explicitly declare the <relation_name>_id
field and either remove or nest the <relation_name>
field separately.
If you rename your relations to not have the trailing _id
, the following will work:
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
class RouteOrderingSerializer(serializers.ModelSerializer):
activity = ActivitySerializer( read_only=True)
class Meta:
model = RouteOrdering
fields = ('id','day','order','route_id','activity','tracks')
(Note that declaring route
instead of route_id
would be more in line with the default behaviour, but less clear in my opinion)
Upvotes: 2
Reputation: 5436
Try this:
class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
class RouteOrderingSerializer(serializers.ModelSerializer):
activity_id = ActivitySerializer()
class Meta:
model = RouteOrdering
fields = ('id','day','order','route_id','activity_id')
Upvotes: 1