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
I was facing this problem and my solution (using DRF 3.6) was to use SerializerMethodField on the object and explicitly query the Membership table like so:
class MembershipSerializer(serializers.ModelSerializer): """Used as a nested serializer by MemberSerializer""" class Meta: model = Membership fields = ('id','group','join_date')class MemberSerializer(serializers.ModelSerializer): groups = serializers.SerializerMethodField() class Meta: model = Member fields = ('id','name','groups') def get_groups(self, obj): "obj is a Member instance. Returns list of dicts""" qset = Membership.objects.filter(member=obj) return [MembershipSerializer(m).data for m in qset]
This will return a list of dicts for the groups key where each dict is serialized from the MembershipSerializer. To make it writable, you can define your own create/update method inside the MemberSerializer where you iterate over the input data and explicitly create or update Membership model instances.
NOTE: As a Software Engineer, I love to use Architectures and I have deeply worked on Layered Approach for Development so I am gonna be Answering it with Respect to Tiers.
As i understood the Issue, Here's the Solutionmodels.py
class Member(models.Model): member_id = models.AutoField(primary_key=True) member_name = models.CharField(max_length = class Group(models.Model): group_id = models.AutoField(primary_key=True) group_name = models.CharField(max_length = 20) fk_member_id = models.ForeignKey('Member', models.DO_NOTHING, db_column='fk_member_id', blank=True, null=True)class Membership(models.Model): membershipid = models.AutoField(primary_key=True) fk_group_id = models.ForeignKey('Group', models.DO_NOTHING, db_column='fk_member_id', blank=True, null=True) join_date = models.DateTimeField()
serializers.py
import serializerclass AllSerializer(serializer.Serializer): group_id = serializer.IntegerField() group_name = serializer.CharField(max_length = 20) join_date = serializer.DateTimeField()
CustomModels.py
imports... class AllDataModel(): group_id = "" group_name = "" join_date = ""
BusinessLogic.py
imports ....class getdata(memberid): alldataDict = {} dto = [] Member = models.Members.objects.get(member_id=memberid) #or use filter for Name alldataDict["MemberId"] = Member.member_id alldataDict["MemberName"] = Member.member_name Groups = models.Group.objects.filter(fk_member_id=Member) for item in Groups: Custommodel = CustomModels.AllDataModel() Custommodel.group_id = item.group_id Custommodel.group_name = item.group_name Membership = models.Membership.objects.get(fk_group_id=item.group_id) Custommodel.join_date = Membership.join_date dto.append(Custommodel) serializer = AllSerializer(dto,many=True) alldataDict.update(serializer.data) return alldataDict
You would technically, have to pass the Request to DataAccessLayer which would return the Filtered Objects from Data Access Layer but as I have to Answer the Question in a Fast Manner so i adjusted the Code in Business Logic Layer!