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
In Python, How to Convert Seconds Since Epoch to a 'Datetime' Object
Count Unique Values Using Pandas Groupby
Python Read JSON File and Modify
Convert Floating Point Number to a Certain Precision, and Then Copy to String
Extract Subset of Key-Value Pairs from Dictionary
Serialize Python Dictionary to Xml
If Range() Is a Generator in Python 3.3, Why How to Not Call Next() on a Range
Read from a Log File as It's Being Written Using Python
It Is More Efficient to Use If-Return-Return or If-Else-Return
How to Set the Absolute Position of Figure Windows with Matplotlib
What Exactly Is Contained Within a Obj._Closure_
Why Don't Methods Have Reference Equality
Comparing Boolean and Int Using Isinstance
Valueerror: Numpy.Dtype Has the Wrong Size, Try Recompiling