第五章 關(guān)系與超鏈接API
寫在前面:
本文翻譯于django rest framework官方文檔,由于網(wǎng)上大多數(shù)django rest framework中文翻譯文檔都有較為多的刪減行為然磷,筆者在學(xué)習(xí)的時(shí)候就覺得不是太方便郑趁,故筆者將官方文檔較為完善的為大家翻譯下,僅供大家學(xué)習(xí)參考姿搜。由于筆者文筆有限寡润,若有寫得不當(dāng)之處,敬請各位同仁指出舅柜;若涉及到侵權(quán)梭纹,請聯(lián)系筆者,筆者將立即刪除致份。
現(xiàn)在变抽,我們的API中的關(guān)系通過使用主鍵來表示,在教程的這一部分中知举,我們將通過使用超鏈接來改善關(guān)系的內(nèi)聚性和可發(fā)現(xiàn)性瞬沦。
1. 為我們的API創(chuàng)建一個(gè)根路徑
現(xiàn)在我們的users
和snippets
都配上了路徑了,但是我們沒有一個(gè)單個(gè)的API的進(jìn)入點(diǎn)雇锡。要?jiǎng)?chuàng)建一個(gè)逛钻,我們可以在一個(gè)常規(guī)的基于函數(shù)的視圖和我們前面介紹的@api_view
裝飾器。我們現(xiàn)在將在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 Framework
的reverse
函數(shù)來返回完全限定的URL立肘;第二边坤,URL Patterns
由便捷的模式來標(biāo)識。
我們現(xiàn)在將我們新建的視圖添加到URL Conf
中谅年,我們現(xiàn)在在snippets/urls.py
中為我們的API根目錄添加一個(gè)新的URL Conf
url(r'^$', views.api_root),
2. 超鏈接我們的API
處理外鍵之間的關(guān)系是Web API設(shè)計(jì)的一個(gè)更具挑戰(zhàn)性的方面茧痒,我們可以選擇多種不同的方式來表示關(guān)系。
- 使用主鍵
- 使用實(shí)體之間的超鏈接
- 在相關(guān)實(shí)體上使用唯一識別的slug字段
- 使用相關(guān)實(shí)體的默認(rèn)的字符串表現(xiàn)形式
- 將相關(guān)實(shí)體嵌套在父表示中
- 一些其他的自定義表示
REST Framework
支持所有的這些格式融蹂,并且可以跨前或反向關(guān)系來應(yīng)用他們旺订,或者將他們應(yīng)用于諸如通用外鍵的自定義管理器弄企。
我們現(xiàn)在在實(shí)體間使用超鏈接的樣式,為了這樣做区拳,我們需要修改我們的序列化器以擴(kuò)展HyperlinkedModelSerializer
來代替已存在的ModelSerializer
對于HyperlinkedModelSerializer
與ModelSerial
有如下的差別:
- 默認(rèn)情況下不包含id字段
- 它包含一個(gè)url字段拘领,使用
HyperlinkedIdentityField
- 關(guān)系使用
HyperlinkedIdentityField
,而不是PrimaryKeyRelatedField
我們可以輕松的重寫我們現(xià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')
3. 確保我們的URL Patterns已命名
如果我們要有一個(gè)超鏈接的API约素,我們需要確保我們我們命名了我們的URL Patterns,我們來看看我們需要命名的URL Patterns
- 指向
user-list
和snippet-list
的我們的API的根 - 用戶的序列化虛包含一個(gè)引用
snippet-detail
的字段 - 默認(rèn)情況下我們的user和snippet的序列化程序包含
url
字段笆凌,默認(rèn)情況下將引用“{model_name}-detail”圣猎,在這樣的情況下,我們要引用的就是snippet-detail
和user-detail
將所有的這些添加到我們的URL Conf之后菩颖,我們的snippets/urls.py
文件將是如下的樣子:
from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
# API的路徑
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'^users/$',
views.UserList.as_view(),
name='user-list'),
url(r'^users/(?P<pk>[0-9]+)/$',
views.UserDetail.as_view(),
name='user-detail')
])
# 登錄和登出
urlpatterns += [
url(r'^api-auth/', include('rest_framework.urls',
namespace='rest_framework')),
]
4. 添加分頁
user和snippet的列表視圖最終可能會(huì)返回很多實(shí)例样漆,我們希望確保分頁結(jié)果,并允許API客戶端逐步的瀏覽每個(gè)單獨(dú)的頁面
我們可以通過修改我們的 tutorial/settings.py 文件晦闰,將默認(rèn)列表樣式更改為使用和分頁放祟,添加如下的設(shè)置:
REST_FRAMEWORK = {
"PAGE_SIZE": 10
}
我們可以注意到REST Framework
的設(shè)置都命名為單個(gè)的字典設(shè)置,這有助于他們和其他的項(xiàng)目設(shè)置保持分離呻右。
5. 下一步
在下一章跪妥,我們將介紹如何使用ViewSets
和Routers
來減少構(gòu)建我們的API所需的代碼量。