官网地址: http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/
目前我们的API中的关系用主键表示,在本教程的这一部分中,我们将改进API的内聚力和可发现性,而不是使用关联的超链接。
1 .为API根创建一个URL
现在我们有了 snippets
与 users
的url, 但没有API的入口 为了创建一个, 我们将使用基于函数的常规视图和我们前面介绍的@api_view装饰器。在 snippets/views.py
中添加:
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
@api_view(['GET'])
def api_root(request, format=None):
return Response({
'users': reverse('user-list', request=request, format=format),
'snippets': reverse('snippet-list', request=request, format=format)
})
这里需要注意两点:
首先, 我们使用REST框架reverse
函数是为了返回一个完全限定的URLS;
其次, URL 匹配方式通过方便的名称来标识,这个稍后会在snippets/urls.py
中声明。
2. 为语法高亮功能常见URL
很明显的意见事是我们的 API 中仍然缺少代码突出显示。
不同于其它的API,我们不想使用JSON,而只是想使用HTML表示. REST框架提供了2种 HTML渲染类型,一个用于使用模板渲染的HTML,另一个是使用已经体检构建好的HTML代码。 这里我们使用第二种方式.
在创建代码高亮视图时,我们需要考虑的另一件事是,我们可以使用现有的具体通用视图。 我们不是返回一个对象实例,而是一个对象实例的属性。
我们将使用最基础的类视图创建.get()
方法来表示实例,而不是使用通用类视图。 在你的 snippets/views.py
添加:
from rest_framework import renderers
from rest_framework.response import Response
class SnippetHighlight(generics.GenericAPIView):
queryset = Snippet.objects.all()
renderer_classes = (renderers.StaticHTMLRenderer,)
def get(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
在 snippets/urls.py
中添加以下url匹配规则:
url(r'^$', views.api_root),
然后添加一个 代码段高亮的url匹配规则
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
3. API超链接
处理实体之间的关系是WEB API 设计更具挑战性之一。我们可以选择很多不同方法来表示关系:
. 使用主键
. 在两个实体之间使用超链接
. 在两个相关的实体上使用唯一的标识字段
. 在两个相关的实体上使用默认的字符串表现形式
. 将相关实体嵌套在父表达式内
. 一些其它自定义表达式
REST框架支持所有这些类型,而且可以将他们应用于正向或反向关系,或者将它们应用于自定义管理器(如通用外键)。
在本例中,我们在两个实体上使用超链接的方式. 为了实现这个,我们将要修改序列化程序来扩展 HyperlinkedModelSerializer
, 而不是现有的ModelSerializer
类HyperlinkedModelSerializer
相比 ModelSerializer
有以下区别:
1) 默认不包含 id
字段
2) 包含一个 url
字段, 使用HyperlinkedIdentityField
3) 关系使用HyperlinkedRelatedField
, 而不是PrimaryKeyRelatedField
我们可以使用超链接很容易的重写我们已存在的序列化方法, 在 snippets/serializers.py
添加:
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
class Meta:
model = Snippet
fields = ('url', 'id', 'highlight', 'owner',
'title', 'code', 'linenos', 'language', 'style')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'snippets')
注意, 我们还添加了一个新的 highlight
字段,改字段与url
字段的类型一样, 不同之处在于它指向snippet-highlight
url 匹配模式, 而不是 snippet-detail
url匹配模式。
因为我们在URL中包含了类似于.json
格式的后缀. 我们还需要在highlight
字段指出,任何返回超链接的后缀格式应该使用.html
的后缀。
4. 确保URL匹配都有命名
如果我们要使用超链接的API, 我们需要确认对URL匹配进行命名(name),看看那个URL匹配需要命名:
. API的根指向user-list
和 snippet-list
. snippet序列化包含一个字段指向 snippet-highlight
. user 序列化包含一个字段指向 snippet-detail
. snippet 和 user 序列化包含url
字段,默认将指向{model_name}-detail
, 在本例中将指向snippet-detail
和 user-detail
在URL配置中完成所有的命名后,我们最终的 snippet/urls.py
应该如下:
from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
# API endpoints
urlpatterns = format_suffix_patterns([
url(r'^$', views.api_root),
url(r'^snippets/$',
views.SnippetList.as_view(),
name='snippet-list'),
url(r'^snippets/(?P<pk>[0-9]+)/$',
views.SnippetDetail.as_view(),
name='snippet-detail'),
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$',
views.SnippetHighlight.as_view(),
name='snippet-highlight'),
url(r'^users/$',
views.UserList.as_view(),
name='user-list'),
url(r'^users/(?P<pk>[0-9]+)/$',
views.UserDetail.as_view(),
name='user-detail')
])
# Login and logout views for the browsable API
urlpatterns += [
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
5. 添加分页
用户和代码段的列表视图可能会返回相当多的实例,因此我们希望对结果进行分页,并允许API客户端逐步浏览每个单独的页面。
我们可以使用分页来改变默认的列表样式, 修改我们的 tutorial/settings.py
文件, 添加如下信息
REST_FRAMEWORK = {
'PAGE_SIZE': 10
}
注意,REST框架的配置都命名到单个字典配置中, 名为REST_FRAMEWORK
, 能很好的与你的其它项目的配置分离开来。
如果需要的话我们也可以自定义分页样式,但在本例中我们使用默认的配置。
6. 浏览API
如果我们打开浏览器并跳转到可浏览的API,你会发现你可以按照你的工作方式通过链接来很简单的浏览API
你也可以看到 高亮 的snippet实例链接, 这将使您转到突出显示的HTML代码表现方式