《django by example》实践 educa 项目(三
关键词:django by example
点我查看本文集的说明及目录。
本项目相关内容包括:
实现过程:
CH12 创建一个API
上一章,我们创建了学生注册和课程报读系统,创建视图展示了课程内容,并学习了如何使用 Django 的缓存框架。本章,我们将学习如何实现以下功能:
- 创建 RESTful API
- 为 API 视图处理授权和权限问题
- 创建 API 的 viewsets 和 routers
创建一个 RESTful API
我们可能需要创建一个接口来使其它服务与自己的 web 应用进行交互。通过 API 可以实现第三方获得信息以及操作应用程序。
我们可以通过几种方法构建 API ,但是推荐遵守 REST 原则。REST 架构源自 Representational State Transfer 。 RESTful APIs 是基于资源的。模型代表资源,GET、POST、PUT 或 DELETE 等 HTTP 方法可以获取、创建、更新或者删除对象。内容也可以使用 HTTP 响应代码,不同的 HTTP 响应码表示不同的 HTTP 请求结果,比如 2XX 响应码表示成功,4XX 响应码表示失败等。
RESTful API 交换数据时最常使用的格式是 JSON 和 XML 。我们使用 JSON 序列化为项目创建一个 REST API 。 API 将提供以下功能:
- 获取主题
- 获取可以获得的课程
- 获取课程内容
- 报读课程
我们可以通过创建自定义视图开始学习使用 Django 构建 API 。然而,一些第三方模块可以简化项目创建 API 的过程,这些第三方模块中最受欢迎的是 Django Rest 框架。
安装 django Rest 框架
django Rest 框架帮助用户轻松地创建项目的 REST API 。我们可以从http://www.django-rest-framework.org/找到 REST 框架的所有信息。
打开 shell 并使用以下命令安装框架:
pip install djangorestframework
编辑 educa 项目的 settings.py 文件并在 INSTALLED_APPS 中添加 rest_framework 来激活应用:
INSTALLED_APPS = ['courses', 'django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'students', 'memcache_status','rest_framework',]
然后,在 settings.py 中添加以下设置:
# REST settings
REST_FRAMEWORK = {'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly']}
我们可以使用 REST_FRAMEWORK 配置 API 。 REST 框架提供很多配置默认行为的设置。 DEFAULT_PERMISSION_CLASSES 设置指定读取、创建、更新或者删除对象的默认权限。 我们将 DjangoModelPermissionsOrAnonReadOnly 设置为唯一的权限类。这个类基于 Django 权限系统,权限系统允许用户创建、更新和删除对象,但匿名用户只能读取对象。后续我们将学习更多的权限。
REST 框架的参数设置列表见http://www.django-rest-framework.org/api-guide/settings/。
定义 serializers
设置好 REST 框架后,需要指定数据如何进行序列化。输出数据应该序列化为特定格式,输入数据应该进行反序列化以便于处理。框架提供以下类来进行单一对象的序列化:
-
Serializer:为普通 Python 类实例提供序列化;
-
ModelSerializer:为模型实例提供序列化,使用主键表示对象关系;
-
HyperlinkedModelSerializer:与 ModelSerializer 相同,但是使用链接表示对象关系。
我们来创建第一个 Serializer 。在 courses 应用目录下创建下面的文件结构:
CH12-1.png我们在 api 目录下创建所有的 API 函数。编辑 serializers.py 文件并添加以下代码:
from rest_framework import serializers
from ..models import Subject
class SubjectSerializer(serializers.ModelSerializer):
class Meta:
model = Subject
fields = ('id', 'title', 'slug')
这是 Subject 模型的 serializer 。serializer 的定义方式与 Form 和 ModelForm 类的定义方式相似。使用 Meta 类来指定进行序列化的模型以及模型包含的字段。如果不设置 fields 属性,则将包含模型所有字段。
我们来测试一下 serializer 。打开命令行并使用 python manage.py shell 打开 Django shell ,运行以下代码:
In [1]: from courses.models import Subject
In [2]: from courses.api.serializers import SubjectSerializer
In [3]: subject = Subject.objects.latest('id')
In [4]: serializer = SubjectSerializer(subject)
In [5]: serializer.data
在这个例子中,我们获取了一个 Subject 对象,创建了一个 SubjectSerializer 实例,并且访问了序列化数据。将得到以下输出:
{'id': 4, 'title': 'Mathematics', 'slug': 'mathematics'}
我们可以看到,模型数据变成了 Python 数据类型。
理解 pasers 和 renderers
HTTP 响应返回序列化数据之前,需要将序列化数据渲染为特定格式。接收到 HTTP 请求时,我们需要解析输入数据并在使用之前对其进行反序列化。 REST 框架包含 renderers 和 parsers 来处理这个过程。
我们来看下如何解析输入数据。对于一个 JSON 字符串输入,可以使用 REST 框架提供的 JSONParser 类来将其转换为 Python 对象。在 Python shell 中执行以下代码:
In [6]: from io import BytesIO
In [7]: from rest_framework.parsers import JSONParser
In [8]: data = b'{"id":4,"title":"Music","slug":"music"}'
In [9]: JSONParser().parse(BytesIO(data))
你应该得到这样的输出:
Out[9]: {u'id': 4, u'slug': u'music', u'title': u'Music'}
REST 框架还包括 Renderer 类来帮助用户格式化 API 响应。框架根据内容确定使用哪个 renderer 。它检查请求的 Accept 头来确定预期的响应内容类型,比如可以由 URL 的格式后缀确定选用的 renderer ,例如,访问将触发 JSONRenderer 来返回 JSON 响应。
回到 shell 并执行以下代码使用前面的序列化例子渲染 serializer 对象:
In [10]: from rest_framework.renderers import JSONRenderer
In [11]: JSONRenderer().render(serializer.data)
输出应该是:
Out[11]: b'{"id":4,"title":"Mathematics","slug":"mathematics"}'
这里使用 JSONRenderer 将序列化数据渲染为 JSON 格式。默认情况下,REST 框架使用两种不同的 renderers:JSONRenderer 和 BrowsableAPIRenderer 。BrowsableAPIRenderer 提供便于浏览 API 的 web 接口。我们可以通过设置 REST_FRAMEWORK 的 DEFAULT_RENDERCLASSES 来更改默认的 renderer 类。
http://www.django-rest-framework.org/api-guide/renderers/ 和http://www.django-rest-framework.org/api-guide/parsers/中有更多关于 renderers 和 parsers 的信息。
创建列表和详情视图
REST 框架内置创建 API 视图的通用视图和 mixin 集合来实现获取、创建、更新或者删除模型对象的功能。http://www.django-rest-framework.org/api-guide/generic-views/中包括 REST 框架提供的所有通用 mixin 和视图。
我们来创建获取 Subject 对象的列表和详情视图。在 courses/api/ 目录下新建一个 views.py 的文件,并添加以下代码:
from rest_framework import generics
from .serializers import SubjectSerializer
from ..models import Subject
class SubjectListView(generics.ListAPIView):
queryset = Subject.objects.all()
serializer_class = SubjectSerializer
class SubjectDetailView(generics.RetrieveAPIView):
queryset = Subject.objects.all()
serializer_class = SubjectSerializer
代码中使用了 REST 框架的通用 ListAPIView 和 RetrieveAPIView。详细视图中包含一个获取给定键对象的 pk URL参数。两个视图都设置了以下属性:
- queryset: 获取对象使用的基础 QuerySet ;
- serializer_class:序列化对象的类;
下面为视图添加 URL模式。在 courses/api/ 目录下新建 urls.py 的文件并添加以下代码:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^subjects/$', views.SubjectListView.as_view(), name='subject_list'),
url(r'^subjects/(?P<pk>\d+)/$', views.SubjectDetailView.as_view(),
name='subject_detail'), ]
编辑 educa 项目的 urls.py 文件并包含以下 API 模式:
url(r'^api/',include('courses.api.urls'))
使用 python manage.py runserver 运行开发服务器,打开 shell 并通过 cURL 获取 http://127.0.0.1:8000/api/subjects/:
curl http://127.0.0.1:8000/api/subjects/
你将得到类似下面的输出:
[{"id":4,"title":"Mathematics","slug":"mathematics"},{"id":3,"title":"Music","slug":"music"},{"id":2,"title":"Physics","slug":"physics"},{"id":1,"title":"Programming","slug":"programming"}]
HTTP响应包含 JSON 格式的 Subject 对象列表。如果你的操作系统没有安装 curl,可以从http://curl.haxx.se/dlwiz/下载。除了 curl ,我们还可以使用其它工具发送 HTTP请求,比如 Postman 浏览器插件(可以从 https://www.getpostman.com 获取)。
在浏览器中打开 http://127.0.0.1:8000/api/subjects/ ,你将看到 REST 框架可以浏览的 API :
CH12-2.png这个 HTML接口由 BrowsableAPIRenderer 提供。它展示了得到的标题和内容,并且允许用户实现请求。我们可以通过在 URL 中添加 id 来访问 Subject 对象的 API 详情视图。在浏览器中打开http://127.0.0.1:8000/api/subjects/1/,你将看到渲染为 JSON 格式的单个对象。
创建嵌套 serializers
我们将为 Course 模型创建 serializer ,编辑 api/serializers.py 文件并添加以下代码:
from ..models import Course
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = (
'id', 'subject', 'title', 'slug', 'overview', 'created', 'owner',
'modules')
我们来看下如何实现 Course 对象序列化,打开 shell ,运行 python manage.py shell ,并运行以下代码:
In [1]: from rest_framework.renderers import JSONRenderer
In [2]: from courses.models import Course
In [3]: from courses.api.serializers import CourseSerializer
In [4]: course = Course.objects.latest('id')
In [5]: serializer = CourseSerializer(course)
In [6]: JSONRenderer().render(serializer.data)
我们将会看到包含 CourserSerializer 设置的字段的 JSON 对象。
b'{"id":2,"subject":4,"title":"Course 2","slug":"course2","overview":"","created":"2018-04-16T15:43:35.885525Z","owner":1,"modules":[5,6]}'
结果中的 modules 管理器的相关对象序列化为主键列表:
"modules":[7,8]
我们希望增加更多模信息,因此需要序列化 Module 对象并进行嵌套。将刚刚添加到 api/serializers.py 中的代码修改为:
from ..models import Course, Module
class ModuleSerializer(serializers.ModelSerializer):
class Meta:
model = Module
fields = ('order', 'title', 'description')
class CourseSerializer(serializers.ModelSerializer):
modules = ModuleSerializer(many=True, read_only=True)
class Meta:
model = Course
fields = (
'id', 'subject', 'title', 'slug', 'overview', 'created', 'owner',
'modules')
这里定义了 ModuleSerializer 来对 Module 模型进行序列化。然后将 modules 属性添加到 CourseSerializer 中来嵌套 ModuleSerializer 。设置 many = True 表示对多个对象进行序列化。read_only 参数表示这个字段是只读的,不能使用任何输入来创建或者修改对象。
打开 shell 并再次创建 CourseSerializer 实例,使用 JSONRenderer 渲染序列化数据。这次,模块列表使用了嵌套的 ModuleSerializer 进行了序列化:
"modules":[{"order":0,"title":"Installing Django","description":"how to install django"},{"order":1,"title":"models","description":"about django model"}]
更多序列化的相关信息见http://www.django-rest-framework.org/api-guide/serializers/。
创建自定义视图
REST 框架提供一个 APIView 类,可以基于 Django View 类实现 API 功能。 APIView 与 View 的区别在于使用 REST 框架 自定义的 Request 和 Response 对象并处理 APIException 异常来返回合适的 HTTP 响应。它还包含内置的授权和权限系统来管理视图访问。
我们将为用户报读课程创建一个视图,编辑 api/views.py 文件并添加以下代码:
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from ..models import Course
class CourseEnrollView(APIView):
def post(self, request, pk, format=None):
course = get_object_or_404(Course, pk=pk)
course.students.add(request.user)
return Response({'enrolled': True})
CourseEnrollView 视图处理课程的用户报读事务,上面的代码实现以下功能:
- 创建自定义的 APIView 子类;
- 为 POST 请求定义 post() 方法,这个视图不允许其它方法;
- 使用 pk URL 参数来表示课程 ID 。获取给定 pk 参数的课程,如果没有对象课程则引发 404 异常;
- 将当前的用户添加到 Course 对象的 students 多对多关系中并返回成功响应。
编辑 api/urls.py 文件并为 CourseEnrollView 添加以下 URL 模式:
url(r'^courses/(?P<pk>\d+)/enroll/$', views.CourseEnrollView.as_view(),
name='course_enroll')
理论上,现在已经可以通过 POST 请求来报读课程,然而,我们还需要识别用户并阻止没有授权的用户访问视图。下面来看下 API 的授权和权限如何工作。
处理授权
REST 框架通过授权类来识别请求用户。如果授权成功,框架将 request.user 设置为授权的 User 对象,如果用户没有授权,Request.user 将设置为 Django AnonymousUser 实例。
REST 框架提供以下授权后端:
-
BasicAuthentication : HTTP 基本授权,客户端在 Authorization HTTP头中发送经过 Base64 编码处理的用户名和密码。https://en.wikipedia.org/wiki/Basic_access_authentication中有详细介绍。
-
TokenAuthertication: 令牌授权。使用 Token 模型来保存用户令牌。通过放在 Authorization HTTP 头中的 token 进行授权。
-
SessionAuthertication:使用 Django 会话后端进行授权。这个后端用于从网站前端向 API 实现授权的 AJAX 请求。
我们可以通过继承 REST 框架提供的 BaseAuthorization 类创建一个自定义授权后端,并覆盖 authenticate() 方法。
每个视图都可以进行授权,也可以使用 DEFAULT_AUTHENTICATION_CLASSES 设置全局授权。
注意:
授权仅能识别请求用户。不能允许或者拒绝访问视图。我们需要使用权限来限制对视图的访问。
我们可以从http://www.django-rest-framework.org/api-guide/authentication/ 找到授权的所有信息。
下面将在视图中添加 BasicAuthentication 。编辑 courses 应用的 api/views.py 并向 CourseEnrollView 添加 authentication_class 属性:
from rest_framework.authentication import BasicAuthentication
class CourseEnrollView(APIView):
authentication_classes = (BasicAuthentication,)
def post(self, request, pk, format=None):
course = get_object_or_404(Course, pk=pk)
course.students.add(request.user)
return Response({'enrolled': True})
这里将通过 HTTP 请求头中的 Authorization 标头凭证来识别用户。
为视图添加权限
REST 框架使用权限系统来限制视图访问。REST 框架内置的权限包括:
- AllowAny : 没有访问限制,用户授权与否都可以访问;
- IsAuthenticated : 只允许授权的用户访问;
- IsAuthenticatedOrReadOnly : 授权用户可以进行完全访问,匿名用户只能进行读操作(如 GET 、 HEAD、或 OPTIONS 操作);
- DjangoModelPermissions : django.contrib.auth 绑定的权限,视图需要设置 queryset 属性。 只有有模型访问权限的用户才能访问。
- DjangoObjectPermissions : 基于对象的 Django 权限。
如果拒绝用户访问,我们通常获得以下 HTTP 错误码:
- HTTP 401 :没授权
- HTTP 403:权限拒绝
我们可以从http://www.django-rest-framework.org/api-guide/permissions/看到更多关于权限的介绍。
编辑 courses 应用的 api/views.py 文件并为 CourseEnrollView 添加 permission_class 属性:
from rest_framework.permissions import IsAuthenticated
class CourseEnrollView(APIView):
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAuthenticated,)
这里添加了 IsAuthorization 权限,将阻止匿名用户访问视图,现在可以向 API 发送 POST 请求了。
保证开发服务器正在运行,打开 shell 并运行以下命令:
curl -i -X POST http://127.0.0.1:8000/api/courses/1/enroll/
你将得到这样的响应:
HTTP/1.0 401 Unauthorized
Date: Mon, 05 Mar 2018 07:00:42 GMT
Server: WSGIServer/0.1 Python/2.7.10
Content-Length: 58
Vary: Accept
Allow: POST, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
WWW-Authenticate: Basic realm="api"
{"detail":"Authentication credentials were not provided."}
这里接收到了预期的 401 HTTP 码,这是由于我们没有授权。使用一个有基本权限的用户,运行以下命令:
curl -i -X POST -u student:password http://127.0.0.1:8000/api/courses/1/enroll/
使用注册过的用户的凭证代替 student:password ,将会看到下面的输出:
HTTP/1.0 200 OK
Date: Mon, 05 Mar 2018 07:07:50 GMT
Server: WSGIServer/0.1 Python/2.7.10
Vary: Accept
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Content-Length: 17
Allow: POST, OPTIONS
{"enrolled":true}
我们可以访问 admin 网站并检查用户是否报读了课程。
创建视图集合和routers
ViewSets 帮助我们定义 API 与 REST 框架(通过 Router 对象)动态创建的 URLs 的交互。使用视图集合,可以避免多个视图使用重复逻辑。视图集合包含 list()、create()、retrieve()、update()、partial_update() 和 destroy() 等实现获取、更新、删除等操作动作的方法。
下面为 Course 模型创建一个视图集合,编辑 api/views.py 并添加以下代码:
from rest_framework import viewsets
from .serializers import CourseSerializer
class CourseViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
创建 ReadOnlyModelViewSet 子类,ReadOnlyModelViewSet 提供只读权限的 list() 和 retrieve() 操作来列出对象集合或获取单个对象。编辑 api/urls.py 并为视图集合创建 router :
from django.conf.urls import url, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register('courses', views.CourseViewSet)
urlpatterns = [
url(r'^subjects/$', views.SubjectListView.as_view(), name='subject_list'),
url(r'^subjects/(?P<pk>\d+)/$', views.SubjectDetailView.as_view(),
name='subject_detail'),
url(r'^courses/(?P<pk>\d+)/enroll/$', views.CourseEnrollView.as_view(),
name='course_enroll'),
url(r'^', include(router.urls)), ]
这里创建了 DefaultRouter 对象并使用 courses 前缀注册视图集合,router 负责为视图集合动态生成 URLs 。
在浏览器中打开 http://127.0.0.1:8000/api/,将会看到 router 在 URL 中列出所有视图集合,如下图所示:
CH12-3.png可以访问 http://127.0.0.1:8000/api/courses/ 来获得课程列表。
可以从 http://www.django-rest-framework.org/api-guide/viewsets/了解更多关于视图集合的消息。可以从http://www.django-rest-framework.org/api-guide/routers/找到更多关于 router 的消息。
为视图集合添加额外动作
Viewsets 还可以添加额外动作。我们来将 CourseEnrollView 视图更改为自定义视图集合动作。编辑
api/views.py 文件并更改 CourseViewSet :
from rest_framework.decorators import action
class CourseViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(methods=['post'], detail=True,
authentication_classes=[BasicAuthentication],
permission_classes=[IsAuthenticated])
def enroll(self, request, *args, **kwargs):
course = self.get_object()
course.students.add(request.user)
return Response({'enrolled': True})
笔者注:
原文代码为:
from rest_framework.decorators import detail_route class CourseViewSet(viewsets.ReadOnlyModelViewSet): queryset = Course.objects.all() serializer_class = CourseSerializer @detail_route(methods=['post'], authentication_classes=[BasicAuthentication], permission_classes=[IsAuthenticated]) def enroll(self, request, *args, **kwargs): course = self.get_object() course.students.add(request.user) return Response({'enrolled': True})
由于 rest_framework 3.10 版本之后将弃用 detail_route,这里使用 action( detail=True )代替了原文中的 detail_route。
这里添加了自定义 enroll() 方法实现视图集合的额外动作,上面的代码功能为:
-
使用框架的 action 装饰器指定这是对单个对象进行操作的动作;
-
可以使用装饰器为动作添加自定义属性,这里指定只有 POST 方法可以访问视图,并且设置了授权类和权限类;
-
使用 self.get_object() 来获得 Course 对象;
-
将当前用户添加到 students 多对多关系中并返回自定义成功响应。
编辑 api/urls.py 文件并删除下面的 URL ,因为不再需要这个链接:
url(r'^courses/(?P<pk>\d+)/enroll/$', views.CourseEnrollView.as_view(),
name='course_enroll'),
然后编辑 api/views.py 文件并删除 CourseEnrollView 类。
现在,报读课程的链接可以通过 router 动态生成,由于使用名为 enroll 的动作自动生成,生成的 URL 与之前的一样。
创建自定义权限
我们期望学生能够访问报读了的课程内容。只有报读了课程的学生才能访问内容。实现这个功能的最好方法是自定义权限类。rest_framework 提供 BasePermission 类来帮助用户定义以下方法:
- has_permission() :视图级别的权限检查;
- has_object_permission() :实例级别的权限检查;
这些方法返回 True 表示成功,返回 False 表示失败。在 courses/api/ 目录下新建 permissions.py 的文件,并添加以下代码:
from rest_framework.permissions import BasePermission
class IsEnrolled(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.students.filter(id=request.user.id).exists()
创建 BasePermission 的子类并重写 has_object_permission() 方法。检查请求的用户是否在 Course 对象的 students 关系中,下一步我们将使用 IsEnrolled 权限。
序列化课程内容
我们需要序列化课程内容, Content 模型内置通用外键来访问不同类型内容模型。前一章,我们还为所有方法模型添加了自定义 render() 方法。这个方法可以为 API 提供渲染的内容。
编辑 courses 应用的 api/serializers.py 文件并添加以下代码:
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')
上面的代码,继承 REST 框架提供的 RelatedField 序列化字段创建自定义字段,并重写 to_representation() 方法。为 Content 模型定义 ContentSerializer 并使用自定义字段表示通用外键 item 。
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):
queryset = Course.objects.all()
serializer_class = CourseSerializer
@action(methods=['post'], detail=True,
authentication_classes=[BasicAuthentication],
permission_classes=[IsAuthenticated])
def enroll(self, request, *args, **kwargs):
course = self.get_object()
course.students.add(request.user)
return Response({'enrolled': True})
@action(methods=['get'], serializer_class=CourseWithContentsSerializer,
authentication_classes=[BasicAuthentication],
permission_classes=[IsAuthenticated])
def contents(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
这个方法的描述如下:
-
使用 detail_route 装饰器指定这个动作应用于单个对象;
-
指定只有 GET 方法可以访问这个动作;
-
使用 CourseWithContentsSerializer 序列化类包含渲染的课程内容;
-
使用 IsAutheticated 和自定义 IsEnrolled 权限指定动作权限,这样可以保证只有订阅了课程的用户才能访问内容。
-
使用存在的 retrieve() 动作返回课程对象。
在浏览器中打开 http://127.0.0.1:8000/api/courses/1/contents/,如果使用具有权限的用户访问视图,将可以看到课程的每个模块,模块包含渲染的 HTML 内容:
CH12-4.png我们已经创建了一个帮助其它服务程序访问课程应用的简单 API 。REST 框架可以使用 ModelViewSet 视图集来管理创建和编辑对象。我们已经介绍了 Django Rest 框架的主要内容,更多扩展内容详见http://www.django-rest-framework.org/。
总结
本章,我们创建了一个 RESTful API 供其它服务与 web 应用交互。
第 13章 上线运行 可以从https://www.packtpub.com/sites/default/files/downloads/Django_By_Example_GoingLive.pdf下载。它将教我们如何通过 uWSGI 和 NGINX 创建生产环境,以及如何实现自定义 middleware 和创建自定义管理命令。
你已经到达了本书的结尾。恭喜你!已经学习了使用 Django 成功地创建 web 应用的技能。这本书引导你开发实际生活中需要的项目以及使用 Django 集成其它技术。现在,你已经为创建自己的 Django 项目做好了准备,不管它是简单的原型还是大型的 web应用程序。
祝下一次的 Django 冒险成功。