在 Django 剩余框架中的响应中包含中间层(通过模型)

我有一个关于处理 m2m/through 模型和它们在 django rest 框架中的表示的问题。让我们举一个经典的例子:

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()

Py:

imports...


class MemberSerializer(ModelSerializer):
class Meta:
model = Member


class GroupSerializer(ModelSerializer):
class Meta:
model = Group

视图:

imports...


class MemberViewSet(ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer


class GroupViewSet(ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer

当 GETING 一个 Member 的实例时,我成功地接收到了所有成员的字段以及它的组——但是我只获得了组的详细信息,而没有从会员模型中获得额外的细节。

换句话说,我收到 期待:

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

注意 加入 _ 日期

我已经尝试了这么多的解决方案,当然包括 Django rest-框架官方页面,但似乎没有人给出一个合适的简单的答案-我需要做什么才能包括这些额外的字段?我发现使用 django-stasypie 更加直接,但是有一些其他的问题,我更喜欢静止框架。

37615 次浏览

不如..。

在 MemberSerializer 上,定义如下字段:

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

然后在您的成员资格序列化程序上,您可以创建以下内容:

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在 DRF 3.0中被重命名为 serializers.ReadOnlyField,因此这应该是:

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

用于任何现代实现

我当时正面临这个问题,我的解决方案(使用 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 序列化每个 dict 的组键的 dict 列表。要使其可写,可以在 MemberSerializer 中定义自己的 create/update 方法,在该方法中迭代输入数据并显式创建或更新 Membership 模型实例。

注意: 作为一名软件工程师,我喜欢使用体系结构,并且我已经深入研究了分层开发方法,所以我将回答关于层的问题。

正如我所理解的问题,这是解决方案 Models.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()

序列化器 py

import serializer


class 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

从技术上讲,您必须将请求传递到 DataAccessLayer,它将从数据访问层返回经过过滤的对象,但由于我必须快速回答这个问题,所以我调整了业务逻辑层的代码!