在Django Rest Framework中包含中介(通过模型)

我有一个关于处理m2m /通过模型及其在django rest框架中的表示的问题。 我们举一个经典的例子:

models.py:

from django.db import models class Member(models.Model): name = models.CharField(max_length = 20) groups = models.ManyToManyField('Group', through = 'Membership') class Group(models.Model): name = models.CharField(max_length = 20) class Membership(models.Model): member = models.ForeignKey('Member') group = models.ForeignKey('Group') join_date = models.DateTimeField() 

serializers.py:

 imports... class MemberSerializer(ModelSerializer): class Meta: model = Member class GroupSerializer(ModelSerializer): class Meta: model = Group 

views.py:

 imports... class MemberViewSet(ModelViewSet): queryset = Member.objects.all() serializer_class = MemberSerializer class GroupViewSet(ModelViewSet): queryset = Group.objects.all() serializer_class = GroupSerializer 

当获得一个会员的实例时,我成功地接收了所有成员的字段以及它的组 – 但是我只获取组的细节,没有来自成员模型的额外细节。

换句话说,我希望得到:

 { 'id' : 2, 'name' : 'some member', 'groups' : [ { 'id' : 55, 'name' : 'group 1' 'join_date' : 34151564 }, { 'id' : 56, 'name' : 'group 2' 'join_date' : 11200299 } ] } 

注意join_date

我已经尝试了很多的解决scheme,当然包括关于它的Django Rest-Framework官方网页,似乎没有人给出正确的答案 – 我需要做些什么来包含这些额外的字段? 我发现它与django-tastypie更直接,但有一些其他问题,宁愿rest框架。

怎么样…..

在你的MemberSerializer上,像这样定义一个字段:

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

然后在你的会员串行器,你可以创build这个:

 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', ) 

这就产生了一个序列化值的总体效果,就是以你想要的成员资格为源,然后使用一个自定义的序列化器来提取你想显示的位。

编辑:作为@bryanph评论, serializers.field被重命名为serializers.ReadOnlyField在DRF 3.0,所以这应该是:

 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', ) 

对于任何现代的实现

我正面临着这个问题,我的解决scheme(使用DRF 3.6)是在对象上使用SerializerMethodField并显式查询Membership表,如下所示:

 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] 

这将返回从MembershipSerializer序列化每个词典的组键的字典列表。 为了使其成为可写,您可以在MemberSerializer中定义您自己的创build/更新方法,在该方法中迭代input数据并显式创build或更新Membership模型实例。