Как включить связанные поля модели с помощью Django Rest Framework?

103

Скажем, что мы имеем следующую модель:

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
        }, 
    ]
},

Возможно ли это? Если да, то как? И это плохая идея?

Теги:
django-rest-framework

2 ответа

165
Лучший ответ

Самый простой способ - использовать аргумент глубины

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, вместо этого убедиться, что атрибут teachers существует, используя параметр related_name в вашей модели Teacher, т.е., classroom = models.ForeignKey(Classroom, related_name='teachers')

Следует иметь в виду, что вложенные сериализаторы в настоящее время не поддерживают операции записи. Для записываемых представлений вы должны использовать регулярные плоские представления, такие как pk или гиперссылка.

  • 0
    Когда я попробовал первое решение, я не получил Учителей, однако я действительно получил экземпляры родителя Классной комнаты (который этот пример не показывает). Во втором решении я получил ошибку - «Объект класса» не имеет атрибута «учителя». Я что-то пропустил?
  • 1
    @Chaz Обновил ответ, чтобы объяснить, почему depth не будет делать то, что вам нужно в этом случае, а также объяснить исключение, которое вы видите, и как с ним бороться.
Показать ещё 11 комментариев
17

Спасибо @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",)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню