跟着Django的教程走例子,遇到了Django REST Framework的内容,可惜教程用的版本有点老,在Django1.5,Python3.3下例子都通不过。在http://django-rest-framework.org的官网上有教程,我看了看,似乎只有前两部分的中文翻译,就趁着自己看也翻一下后面的部分,自己学习,供大家参考:如有错讹,请多指教。
教程 5 - 关系 & 超链接API
到目前为止,在我们的API中关系(relationship)还是通过主键来表示的。在这部分的教程中,我们将用超链接方式来表示关系,从而提升API的统一性和可发现性。
为API根创建一个endpoint
到目前为止,我们已经有了'snippets'和'users'的endpoint, 但是我们还没有为我们的API单独创立一个端点入口。我们可以用常规的基于函数的view和之前介绍的 @api_view
修饰符来创建。
from rest_framework import renderers 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 framework 的 reverse
函数来返回完全合规的URLs.
为高亮的Snippet创建一个endpoint
我们目前还没有为支持代码高亮的Snippet创建一个endpoints.
与之前的API endpoints不同, 我们将直接使用HTML呈现,而非JSON。在 REST framework中有两种风格的HTML render, 一种使用模板来处理HTML,一种则使用预先处理的方式。在这里我们使用后者。
另一个需要我们考虑的是,对于高亮代码的view并没有具体的泛型view可以直接利用。我们将只返回实例的一个属性而不是对象实例本身。
没有具体泛型view的支持,我们使用基类来表示实例,并创建我们自己的 .get()
方法。在你的 snippets.views 中增加:
from rest_framework import renderers from rest_framework.response import Response class SnippetHighlight(generics.SingleObjectAPIView): model = Snippet renderer_classes = (renderers.StaticHTMLRenderer,) def get(self, request, *args, **kwargs): snippet = self.get_object() return Response(snippet.highlighted)
和以往一样,我们需要为新的view增加新的URLconf,如下增加urlpatterns:
url(r'^$','api_root'),
还需要为代码高亮增加一个urlpatterns:
url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
API超链接化
在Web API设计中,处理实体间关系是一个有挑战性的工作。我们有许多方式来表示关系:
- 使用主键;
- 使用超链接;
- 使用相关实体唯一标识的字段;
- 使用相关实体的默认字符串表示;
- 在父级表示中嵌入子级实体;
- 其他自定义的表示。
REST framework支持所有这些方式,包括正向或者反向的关系,或者将其应用到自定义的管理类中,例如泛型外键。
在这部分,我们使用超链接方式。为了做到这一点,我们需要在序列化器中用 extendHyperlinkedModelSerializer
来替代之前的 ModelSerializer
.
HyperlinkedModelSerializer
与 ModelSerializer 有如下的区别
:
- 缺省状态下不包含
pk
字段; - 具有一个
url
字段,即HyperlinkedIdentityField类型
. - 用
HyperlinkedRelatedField表示关系,而非
PrimaryKeyRelatedField
.
我们可以很方便的改写现有代码来使用超连接方式:
class SnippetSerializer(serializers.HyperlinkedModelSerializer): owner = serializers.Field(source='owner.username') highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html') class Meta: model = models.Snippet fields = ('url', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style') class UserSerializer(serializers.HyperlinkedModelSerializer): snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail') class Meta: model = User fields = ('url', 'username', 'snippets')
注意:我们也增加了一个新的 'highlight'
字段。该字段与 url
字段相同类型。不过它指向了 'snippet-highlight'的
url pattern, 而非'snippet-detail'
的url pattern.
因为我们已经有一个 '.json'的后缀,为了更好的表明高亮字段链接的区别,使用一个
'.html'
的后缀。
正确使用URL patterns
如果要使用超链接API,就必须确保正确的命名和使用 URL patterns. 我们来看看我们需要命名的 URL patterns:
- 指向
'user-list'
和'snippet-list' 的API根
. - snippet的序列化器,包括一个
'snippet-highlight'字段
. - user序列化器,包含一个
'snippet-detail'字段
. - snippet 和user的序列化器,包含
'url'
字段(会缺省指向'snippet-detail'
和'user-detail'
.
一番工作之后,最终的 'urls.py'
文件应该如下所示:
# API endpoints urlpatterns = format_suffix_patterns(patterns('snippets.views', url(r'^$', '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 += patterns('', url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), )
添加分页
列表view有时会返回大量的实例结果,所以我们应该把结果分页显示,以便用户使用。
通过在 settings.py 中
添加如下配置,我们就能在结果列表中增加分页的功能:
REST_FRAMEWORK ={'PAGINATE_BY':10}
请注意REST framework的所有配置信息都是存放在一个叫做 'REST_FRAMEWORK'的dictionary中,以便于其他配置区分。
如有必要,你也可以自定义分页的方式,这里不再赘述。
回顾我们的工作
如果我们打开浏览器来看看之前的API,会发现它们可以用链接的方式工作了。
当你查看snippet实例的 'highlight' 链接时,你会直接看到代码高亮的HTML呈现。
我们目前已经完成了全套的Web API。可以浏览,支持认证,对象粒度的权限,以及多种返回格式。
我们已经完成了流程中的所有步骤,了解了如何从基本的Django View出发,根据需求逐步定义我们的工作方式。
你能从GitHub上得到教程的最终代码: tutorial code ,或者直接访问在线示例: the sandbox.
总结与后续工作
我们的教程已经到此结束,如果你还想更多的了解 REST framework,可以从下面这些地方开始:
- 为 GitHub 做贡献,审查、提交内容或提出新要求。
- 参加讨论组 REST framework discussion group, 帮助创建更好的线上社区.
- Follow the author 作者的 Twitter,打打招呼。
让我们去大展身手吧.
【translated by Hillfree @ 2013年3月29日11:39:27】