Сериализация содержимого курса

Необходимо сериализовать содержимое курса. Модель Content содержит универсальный внешний ключ, который позволяет связывать объекты различных моделей содержимого. Тем не менее, в предыдущей главе мы добавили общий метод render() для всех моделей содержимого. Этот метод можно использовать для предоставления содержимого нашему API.

Отредактируйте файл api/serializers.py приложения courses и добавьте в него следующий код:

from ..models import Content


class ItemRelatedField(serializers.RelatedField):
    def to_representation(self, value):
        return value.render()


class ContentSerializer(serializers.ModelSerializer):
    item = ItemRelatedField(read_only=True)

    class Meta:
        model = Content
        fields = ('order', 'item')

В этом коде мы определяем настраиваемое поле, подклассом сериализатора RelatedField, предоставляемым REST Framework, и переопределением метода to_representation(). Мы определяем сериализатор ContentSerializer для модели Content и используем настраиваемое поле item для генерации foreign key.

Нам нужен альтернативный сериализатор для модели Module, включающий его содержимое, а также расширенный сериализатор Course. Измените файл api/serializers.py и добавьте в него следующий код:

class ModuleWithContentsSerializer(serializers.ModelSerializer):
    contents = ContentSerializer(many=True)

    class Meta:
        model = Module
        fields = ('order', 'title', 'description', 'contents')


class CourseWithContentsSerializer(serializers.ModelSerializer):
    modules = ModuleWithContentsSerializer(many=True)

    class Meta:
        model = Course
        fields = ('id', 'subject', 'title', 'slug', 'overview', 'created', 'owner', 'modules')

Давайте создадим представление, которое имитирует поведение действия retrieve(), но включает содержимое курса. Измените файл api/views.py и добавьте следующий метод в класс CourseViewSet:

from .permissions import IsEnrolled
from .serializers import CourseWithContentsSerializer


class CourseViewSet(viewsets.ReadOnlyModelViewSet):
    # ...
    @detail_route(methods=['get'],
                  serializer_class=CourseWithContentsSerializer,
                  authentication_classes=[BasicAuthentication],
                  permission_classes=[IsAuthenticated, IsEnrolled])
    def contents(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

Описание этого метода выглядит следующим образом:

  • Мы используем декоратор detail_route, чтобы указать, что это действие выполняется для одного объекта.
  • Мы указываем, что для этого действия разрешен только метод GET.
  • Мы используем новый класс сериализатора CourseWithContentsSerializer, который включает содержимое курса.
  • Мы используем IsAuthenticated, так и кастомный IsEnrolled. Таким образом, мы убедимся, что только пользователи, зарегистрировавшиеся на курс, смогут получить доступ к его содержимому.
  • Для возврата объекта курса используется существующее действие retrieve().

Откройте в браузере http://127.0.0.1:8000/api/courses/1/contents/ . При доступе к просмотру с помощью правильных учетных данных будет видно, что каждый модуль курса включает в себя отображаемый HTML-код для содержимого курса, например:

{
"order": 0,
"title": "Installing Django",
"description": "",
"contents": [
    {
        "order": 0,
        "item": "<p>Take a look at the following video for installing Django:</p>\n"
    },
    {
        "order": 1,
        "item": "\n<iframe width=\"480\" height=\"360\" src=\"http://www.youtube.com/embed/bgV39DlmZ2U?wmode=opaque\" frameborder=\"0\"allowfullscreen></iframe>\n\n"
    }
]
}

Вы создали простой интерфейс API, позволяющий другим службам программным образом обращаться к приложению курса. REST Framework также позволяет управлять созданием и редактированием объектов с помощью набора представлений ModelViewSet. Мы покрыли основные аспекты Django Rest Framework, но вы найдете дополнительную информацию о ее функциях в ее обширной документации здесь: http://www.django-rest-framework.org/

results matching ""

    No results matching ""