如何在Django Rest Framework中包含相关模型字段?
假设我们有一个这样的模型:
class Classroom(models.Model):
room_number = [...]
class Teacher(models.Model):
name = [...]
tenure = [...]
classroom = models.ForeignKey(Classroom)
假设我们希望得到的结果不是像ManyRelatedPrimaryKeyField函数那样的结果:
{
"room_number": "42",
"teachers": [
27,
24,
7
]
},
而是返回一个包含完整相关模型信息的结果,比如:
{
"room_number": "42",
"teachers": [
{
'id': 27,
'name': 'John',
'tenure': True
},
{
'id': 24,
'name': 'Sally',
'tenure': False
},
]
},
这样做可能吗?如果可以的话,怎么做?这样做是不是个坏主意?
4 个回答
这可以通过一个非常好用的 Django 包来实现,叫做 drf-flex-fields。我们在用这个包,效果非常棒。你只需要安装它,方法是运行 pip install drf-flex-fields
,然后把它放到你的序列化器里,添加 expandable_fields
,就大功告成了(下面有示例)。这个包还允许你使用点号表示法来指定深层嵌套的关系。
from rest_flex_fields import FlexFieldsModelSerializer
class ClassroomSerializer(FlexFieldsModelSerializer):
class Meta:
model = Model
fields = ("teacher_set",)
expandable_fields = {"teacher_set": (TeacherSerializer, {"source": "teacher_set"})}
接着,你在你的 URL 后面加上 ?expand=teacher_set
,这样就能返回一个扩展的响应了。希望这能在某一天帮助到某个人。干杯!
谢谢你,@TomChristie!!!
你帮了我很多忙!
我想稍微更新一下这个内容(因为我遇到了一个错误)
class TeacherSerializer(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = ('id', 'name', 'tenure')
class ClassroomSerializer(serializers.ModelSerializer):
teachers = TeacherSerializer(source='teacher_set', many=True)
class Meta:
model = Classroom
field = ("teachers",)
最简单的方法是使用 深度参数。
class ClassroomSerializer(serializers.ModelSerializer):
class Meta:
model = Classroom
depth = 1
不过,这样做只会包含正向关系的数据,而在这个例子中,你需要的是反向关系的数据,因为教师字段是反向关系。
如果你有更复杂的需求(比如需要包含反向关系、嵌套某些字段但不嵌套其他字段,或者只嵌套特定的一部分字段),你可以 嵌套序列化器,例如...
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
注意,我们在序列化器字段上使用了 source 参数来指定用作字段来源的属性。我们也可以不使用 source
参数,而是通过在 Teacher
模型上使用 related_name 选项来确保 teachers
属性存在,比如 classroom = models.ForeignKey(Classroom, related_name='teachers')
。
需要记住的一点是,嵌套序列化器目前不支持写操作。如果需要可写的表示方式,应该使用常规的扁平表示,比如主键(pk)或超链接。