Reputation: 183
I have a basic setup using the Django Rest Framework. I have two models and a nested serializer setup:
from django.db import models
class Plan(models.Model):
name = models.CharField(max_length='100')
def __unicode__(self):
return u'%s' % (self.name)
class Group(models.Model):
plan = models.ForeignKey('plan')
name = models.CharField(max_length='50')
weight = models.SmallIntegerField()
def __unicode__(self):
return u'%s - %s' % (self.name, self.plan.name)
from plans.models import Plan, Group
from rest_framework import serializers
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ('name', 'weight')
class PlanSerializer(serializers.ModelSerializer):
group = GroupSerializer(many=True, read_only=True)
class Meta:
model = Plan
fields = ('name', 'group')
from rest_framework import viewsets
from plans.models import Plan
from plans.serializers import PlanSerializer
class PlanViewSet(viewsets.ModelViewSet):
queryset = Plan.objects.all()
serializer_class = PlanSerializer
When I view the serializers relationships in Django's Shell it shows the relationship correctly:
PlanSerializer():
name = CharField(max_length='100')
group = GroupSerializer(many=True, read_only=True):
name = CharField(max_length='50')
weight = IntegerField()
What I end up getting back via cURL is:
[
{
name: Test Plan
}
]
What I expect to get back is:
[
{
name: Test Plan,
group: [
{
name: Test Group,
weight: 1
}
]
}
]
There is no nested data coming through. I'm at a lose for what I've not setup correctly here. Can anyone point me in the correct direction?
Upvotes: 16
Views: 8605
Reputation: 14355
Although not directly applicable to the OP, this may help others that end up here based on the title:
DRF nested serializer not showing related data
This problem also arises if you specify an invalid source
value.
For example, if you accidentally try to use django filter notation (a__b
) when specifying related objects:
class MySerializer(...):
...
my_field = MyOtherSerializer(
source='my_related_field__some_set', many=True, read_only=True
)
In DRF 3.15.2, this does not produce an error. Instead it fails silently: my_field
simply does not show up in the serialized data.
To fix this, use dotted notation, as mentioned in the docs:
source='my_related_field.some_set'
This does work, but beware: If my_related_field
is null, we still get a missing my_field
.
Upvotes: 0
Reputation: 5866
Never forget to give related name for the foreign key. for eg
In models
plan = modles.ForeignKey(Plan, related_name="plan")
In Serializers
plan = PlanSerializers(many = True, read_only = True)
Upvotes: 3
Reputation: 16050
The problem comes from your queryset
: queryset = Plan.objects.all()
. None of the items in this queryset
has .group
attribute that's why your result is empty. By default Django creates a reverse relation of the plan
ForeignKey called group_set
(unless you don't rename it via related_name
) (this means that every plan
item in the queryset
have a group_set
attribute which is a queryset containing all the groups of this plan
). You can use this attribute in order to get a proper serialization. This means to change:
class PlanSerializer(serializers.ModelSerializer):
group_set = GroupSerializer(many=True, read_only=True)
class Meta:
model = Plan
fields = ('name', 'group_set')
If you really want to stick with group
(btw this is a very bad name for a list of groups). You can hack it with prefetch_related
like so:
queryset = Plan.objects.prefetch_related('group_set', to_attr='group')
this way every plan
item will have a group
attribute - a queryset
containing all the groups for this plan
.
Upvotes: 23