目前我們使用主鍵來表示模型之間的關(guān)系。在本章,我們將提高API的凝聚性和可讀性。
為我們API的根節(jié)點(diǎn)創(chuàng)建URL
之前我們給snippets和users創(chuàng)建了URL接口,但我們沒有一個(gè)根節(jié)點(diǎn)的URL。
在此我們創(chuàng)建一個(gè)簡(jiǎn)單的,基于函數(shù)的views,并為它加上@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)
})
需要注意兩點(diǎn):
- 我們使用REST框架中的
reverse方法來返回完全符合規(guī)則的url - url參數(shù)將會(huì)與我們之后在
snippets/urls中定義的相同
編寫snippets/urls.py
url(r'^$', views.api_root),
為高亮代碼創(chuàng)建URL
接下來我們需要為高亮代碼提供接口,和其它的接口不同,這個(gè)接口我們需要展現(xiàn)渲染好的HTML頁面,而不是JSON。
REST框架給我們提供了兩種HTML展現(xiàn)形式,一種是使用模板渲染,一種是使用已經(jīng)提前渲染好的HTML,在此我們使用第二種。
另外,我們需要考慮當(dāng)創(chuàng)建代碼高亮的view時(shí),我們沒有現(xiàn)成的類來繼承,因?yàn)槲覀儾皇欠祷貙?duì)象,而是返回對(duì)象的一個(gè)屬性,我們需要重寫父類的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(r'^snippets/(?P<pk>[0-9]+)/highlight/$', views.SnippetHighlight.as_view()),
API之間使用超鏈接
在Web API中處理各個(gè)API之間的關(guān)系是一件非常頭疼的事情,通常有以下方法表示關(guān)系:
- 使用主鍵
- 在API之間使用超鏈接
- 在關(guān)聯(lián)API之間使用唯一字段表示
- 在關(guān)聯(lián)API之間使用默認(rèn)字符串表示
- 將一個(gè)API嵌套在另一個(gè)API類中
- 其它
REST框架支持上述所有方法,并且可以應(yīng)用于正向、反向關(guān)系或類似外鍵這類自定義管理項(xiàng)。
在這里我們使用超鏈接來處理之間的關(guān)系,因此我們需要修改serializers,使用HyperlinkedModelSerializer替代原先的ModelSerializer:
- 默認(rèn)不包含主鍵
- 使用
HyperlinkedRelatedField時(shí),需要在Meta子類的fields中包含``urls`字段 - 使用
HyperlinkedRelatedField來代替PrimaryKeyRelatedField表示關(guān)系
編輯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')
這里在SnippetSerializer中新增了一個(gè)highlight屬性,這個(gè)屬性和url字段類型相同,區(qū)別在于它指向的是snippet-highlight而非snippet-detail
另外,由于我們有.json格式的后綴,我們需要指定highlight字段使用.html來返回相應(yīng)的格式
確保URL都被命名
在此之前我們創(chuàng)建了一些url參數(shù),在此羅列:
- 根節(jié)點(diǎn)指向了
user-list和snippet-list -
snippet serializer包含了一個(gè)指向snippet-highlight的url的字段 -
user serializer包含了指向snippet-detail的url的字段 -
snippet serializer和user serializer都包含了url字段,這個(gè)字段默認(rèn)指向{model_name}-detail,這里分別是snippet-detail和user-detail
編輯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')),
]
添加分頁
后面可能會(huì)有很多個(gè)數(shù)據(jù)產(chǎn)生,我們需要對(duì)返回結(jié)果進(jìn)行分頁,修改tutorial/settings.py
REST_FRAMEWORK = {
'PAGE_SIZE': 10
}
注意,所有關(guān)于REST框架的settings都在一個(gè)叫做REST_FRAMEWORK的字典中,這幫助我們與其他的settings分離開來。
關(guān)于
本人是初學(xué)Django REST framework,Django REST framework 學(xué)習(xí)紀(jì)要系列文章是我從官網(wǎng)文檔學(xué)習(xí)后的初步消化成果,如有錯(cuò)誤,歡迎指正。
學(xué)習(xí)用代碼Github倉庫:shelmingsong/django_rest_framework
本文參考的官網(wǎng)文檔:Tutorial 5: Relationships & Hyperlinked APIs
博客更新地址
- 宋明耀的博客 [ 第一時(shí)間更新 ]
- 知乎專欄 Python Cookbook
- 簡(jiǎn)書 流月0的文章