在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模型实例。