如何使用Django Rest Framework包含相关的模型字段?

Cha*_*haz 140 python django django-rest-framework

假设我们有以下模型:

class Classroom(models.Model):
    room_number = [....]

class Teacher(models.Model):
    name = [...]
    tenure = [...]
    classroom = models.ForeignKey(Classroom)
Run Code Online (Sandbox Code Playgroud)

假设不是按照ManyRelatedPrimaryKeyField函数得到这样的结果:

{
    "room_number": "42", 
    "teachers": [
        27, 
        24, 
        7
    ]
},
Run Code Online (Sandbox Code Playgroud)

让它返回包含完整相关模型表示的东西,如:

{
    "room_number": "42", 
    "teachers": [
        {
           'id':'27,
           'name':'John',
           'tenure':True
        }, 
        {
           'id':'24,
           'name':'Sally',
           'tenure':False
        }, 
    ]
},
Run Code Online (Sandbox Code Playgroud)

这可能吗?如果是这样,怎么样?这是个坏主意吗?

Tom*_*tie 224

最简单的方法是使用depth参数

class ClassroomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Classroom
        depth = 1
Run Code Online (Sandbox Code Playgroud)

但是,这只包括前向关系的关系,在这种情况下,这种关系并不是你所需要的,因为教师领域是一种反向关系.

如果您有更复杂的要求(例如,包括反向关系,嵌套某些字段,而不是其他字段,或只嵌套字段的特定子集),您可以嵌套序列化程序,例如......

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
Run Code Online (Sandbox Code Playgroud)

请注意,我们使用序列化程序字段上的source参数指定要用作字段源的属性.我们可以source通过在模型上teachers使用related_name选项确保属性存在来删除参数Teacher,即.classroom = models.ForeignKey(Classroom, related_name='teachers')

要记住的一件事是嵌套序列化程序当前不支持写操作.对于可写表示,您应该使用常规的平面表示,例如pk或超链接.

  • 嵌套序列化器非常棒!我必须这样做,并使用DRF 3.1.0.我必须包括`many = True`就像这样`... TeacherSerializer(source ='teacher_set',many = True)`.否则我收到以下错误:`序列化程序字段可能命名不正确,并且不匹配'RelatedManager'实例上的任何属性或键.原始异常文本是:'RelatedManager'对象没有属性'type' (13认同)
  • 嗨@TomChristie,感谢您的回答。我自己也在努力解决这个问题,但我不明白的一件事是 `teachers = TeacherSerializer(source='teacher_set')` 中的 `_set` 来自哪里。我尝试搜索 DRF 文档,但一无所获。有什么提示吗? (2认同)
  • ForeignKey的反面默认将命名为"..._ set".有关更多详细信息,请参阅Django文档:https://docs.djangoproject.com/en/1.10/ref/models/relations/#django.db.models.fields.related.RelatedManager (2认同)

小智 32

谢谢@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",)
Run Code Online (Sandbox Code Playgroud)

  • 如果要过滤怎么办,teachers_set (2认同)

Pau*_*ett 5

这也可以通过使用一个非常方便的dandy 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"})}
Run Code Online (Sandbox Code Playgroud)

然后您添加?expand=teacher_set到您的 URL 并返回扩展响应。希望这有助于某人,有一天。干杯!