API(五)之Relationships & Hyperlinked APIs
目前,我們的API中的關系用主鍵表示。在本教程的這一部分中,我們將改進API的內聚力和可發現性,而不是使用關聯的超鏈接。
為我們的API的根創建一個端點
現在我們有‘snippets‘和‘users‘的端點,但是我們的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中
聲明。
為 highlighted snippets創建端點
我們的pastebin API中仍然缺少的另一個明顯的事情是 the code highlighting endpoints。
與所有其他API端點不同,我們不想使用JSON,而只是呈現HTML表現層。REST框架提供了兩種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)
像往常一樣,我們需要在URLconf中添加新視圖。我們將在snippets/urls.py
中為我們的新API根添加一個url模式:
url(r‘^$‘, views.api_root),
然後為 snippet highlights添加一個url模式:
url(r‘^snippets/(?P<pk>[0-9]+)/highlight/$‘, views.SnippetHighlight.as_view()),
Hyperlinking our API
處理entities之間的關系是Web API設計中更具挑戰性的方面之一。我們可以選擇一些不同的方式來代表一種關系:
- 使用主鍵。
- 在實體之間使用超鏈接。
- 在相關實體上使用唯一的標識字段。
- 使用相關實體的默認字符串表示形式。
- 將相關實體嵌套在父表示內。
- 一些其他自定義表示。
REST框架支持所有這些樣式,並且可以將它們應用於正向或反向關系,也可以在諸如通用外鍵之類的自定義管理器上應用。
在這種情況下,我們希望在實體之間使用超鏈接樣式。為了這樣做,我們將修改我們的序列化程序來擴展HyperlinkedModelSerializer
而不是現有的ModelSerializer
。
HyperlinkedModelSerializer
與ModelSerializer
有以下區別:
- 默認情況下不包括id字段。
- 它包括一個使用
HyperlinkedIdentityField的url字段
。 - 關系使用
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‘
後綴。
Making sure our URL patterns are named
如果我們要使用超鏈接類型的API,那麽我們需要命名URL模式。我們來看看我們需要命名的URL模式。
- 我們的API的根源是指
‘user-list‘
和‘snippet-list‘
。 - 我們的片段serializer包括一個引用
‘snippet-highlight‘
的字段。 - 我們的用戶serializer包括一個引用
‘snippet-detail‘
的字段。 - 我們的片段和用戶序列化程序包括默認情況下將引用
‘{model_name}-detail‘
的‘url‘字段,在這種情況下將是‘snippet-detail‘
和‘user-detail‘
。
將所有這些名字添加到我們的URLconf中後,最終snippets/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‘)), ]
添加分頁
用戶和代碼段的列表視圖可能會返回相當多的實例,因此我們希望確保分頁結果,並允許API客戶端逐步瀏覽每個單獨的頁面。
我們可以通過稍微修改我們的tutorial/settings.py
文件來更改默認列表樣式來使用分頁。添加以下設置:
REST_FRAMEWORK = { ‘PAGE_SIZE‘: 10 }
請註意,REST框架中的設置都命名為單個字典設置,名為“REST_FRAMEWORK”,這有助於保持與其他項目設置的良好分離。
我們也可以自定義分頁風格,如果我們需要,但在這種情況下,我們將堅持默認。
API(五)之Relationships & Hyperlinked APIs