Include Intermediary (Through Model) in Responses in Django Rest Framework

Include intermediary (through model) in responses in Django Rest Framework

How about.....

On your MemberSerializer, define a field on it like:

groups = MembershipSerializer(source='membership_set', many=True)

and then on your membership serializer you can create this:

class MembershipSerializer(serializers.HyperlinkedModelSerializer):

id = serializers.Field(source='group.id')
name = serializers.Field(source='group.name')

class Meta:
model = Membership

fields = ('id', 'name', 'join_date', )

That has the overall effect of creating a serialized value, groups, that has as its source the membership you want, and then it uses a custom serializer to pull out the bits you want to display.

EDIT: as commented by @bryanph, serializers.field was renamed to serializers.ReadOnlyField in DRF 3.0, so this should read:

class MembershipSerializer(serializers.HyperlinkedModelSerializer):

id = serializers.ReadOnlyField(source='group.id')
name = serializers.ReadOnlyField(source='group.name')

class Meta:
model = Membership

fields = ('id', 'name', 'join_date', )

for any modern implementations

Nested serializer Through model in Django Rest Framework

Based on the way you would like to show your output, I suggest you change your models to:

class Group(models.Model):
name = models.CharField(max_length=20)
members = models.ManyToManyField(
'Membership',
related_name='groups',
related_query_name='groups',
)

class Member(models.Model):
name = models.CharField(max_length=20)

class Membership(models.Model):
group = models.ForeignKey(
'Group',
related_name='membership',
related_query_name='memberships',
)
join_date = models.DateTimeField()

How Group model and Member model are ManytoMany, does not have a problem you let the relationship in Group model. It will be the easiest to output it in serialize. related_name and related_query_name are used to make the serialization and point the nested relation.

And finally, your serialize could be like this (I exemplified it with a create method):

class MembershipSerializer(ModelSerializer):
class Meta:
fields = ("id", "join_date",)

class GroupSerializer(ModelSerializer):
memberships = MembershipSerializer(many=True)

class Meta:
model = Group
fields = ("id", "name", "memberships",)

class MemberSerializer(ModelSerializer):
groups = GroupSerializer(many=True)

class Meta:
model = Member
fields = ("id", "name", "groups")

def create(self):
groups_data = validated_data.pop('groups')
member = Member.objects.create(**validated_data)
for group in groups_data:
memberships_data = group.pop('memberships')
Group.objects.create(member=member, **group)
for memberhip in memberships:
Membership.objects.create(group=group, **memberships)

The output will be:

{
"id": 1,
"name": "Paul McCartney",
"groups": [
{
"id": 3,
"name": "Beatles",
"memberships": [
{
"id": 2,
"join_date": "2018-08-08T13:43:45-0300"
}
]
}
]
}

In this output, I am not "nesting" the parent id but you can make it too, just declare into fields attributes.

Appending the logged-in User to Django REST framework POST model update

You can assign the user inside the save() method.


serializer_event = EventSerializer(data=request.data)
if serializer_event.is_valid():
print(serializer_event.validated_data)
serializer_event.save(user=request.user)
return Response(serializer_event.data, status=status.HTTP_201_CREATED)

How do I include related model fields using Django Rest Framework?

The simplest way is to use the depth argument

class ClassroomSerializer(serializers.ModelSerializer):
class Meta:
model = Classroom
depth = 1

However, that will only include relationships for forward relationships, which in this case isn't quite what you need, since the teachers field is a reverse relationship.

If you've got more complex requirements (eg. include reverse relationships, nest some fields, but not others, or nest only a specific subset of fields) you can nest serializers, eg...

class TeacherSerializer(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = ('id', 'name', 'tenure')

class ClassroomSerializer(serializers.ModelSerializer):
teachers = TeacherSerializer(source='teacher_set')

class Meta:
model = Classroom

Note that we use the source argument on the serializer field to specify the attribute to use as the source of the field. We could drop the source argument by instead making sure the teachers attribute exists by using the related_name option on your Teacher model, ie. classroom = models.ForeignKey(Classroom, related_name='teachers')

One thing to keep in mind is that nested serializers do not currently support write operations. For writable representations, you should use regular flat representations, such as pk or hyperlinking.

Serialize JSON with a python keyword using the django-rest-framework

you can do this by overriding to_internal_value and to_representation in your serializer.

class MyModelSerializer(serializers.ModelSerializer):
def Meta:
model = MyModel
fields = ...

def to_internal_value(self, data):
instance = super(MyModelSerializer, self).to_internal_value(data)
instance.import_flag = data.get('import')

def to_representation(self, instance):
data = super(MyModelSerializer, self).to_representation(instance)
data['import'] = instance.import_flag


Related Topics



Leave a reply



Submit