Serializing course contents

We need to serialize course contents. The Content model includes a generic foreign key that allows us to associate objects of different content models. Yet, we have added a common render() method for all content models in the previous chapter. We can use this method to provide rendered contents to our API.

Edit the api/serializers.py file of the courses application and add the following code to it:

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']

In this code, we define a custom field by subclassing the RelatedField serializer field provided by REST framework and overriding the to_representation() method. We define the ContentSerializer serializer for the Content model and use the custom field for the item generic foreign key.

We need an alternate serializer for the Module model that includes its contents, and an extended Course serializer as well. Edit the api/serializers.py file and add the following code to it:

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']

Let's create a view that mimics the behavior of the retrieve() action, but it includes the course contents. Edit the api/views.py file and add the following method to the CourseViewSet class:

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)

The description of this method is as follows:

  • We use the detail_route decorator to specify that this action is performed on a single object.
  • We specify that only the GET method is allowed for this action.
  • We use the new CourseWithContentsSerializer serializer class that includes rendered course contents.
  • We use both the IsAuthenticated and our custom IsEnrolled permissions. By doing so, we make sure that only users enrolled in the course are able to access its contents.
  • We use the existing retrieve() action to return the Course object.

Open http://127.0.0.1:8000/api/courses/1/contents/ in your browser. If you access the view with the right credentials, you will see that each module of the course includes the rendered HTML for course contents, as follows:

{
"order": 0,
"title": "Introduction to Django",
"description": "Brief introduction to the Django Web Framework.",
"contents": [
{
"order": 0,
"item": "<p>Meet Django. Django is a high-level
Python Web framework
...</p>"
},
{
"order": 1,
"item": " <iframe width="480" height="360"
src="http://www.youtube.com/embed/bgV39DlmZ2U?
wmode=opaque"
frameborder="0" allowfullscreen></iframe> "
}
]
}

You have built a simple API that allows other services to access the course application programmatically. REST framework also allows you to handle creating and editing objects with the ModelViewSet view set. We have covered the main aspects of Django REST framework, but you will find further information about its features in its extensive documentation at https://www.django-rest-framework.org/.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.94.153