[Django REST FrameWork][5]:關(guān)系和超鏈接API

目前我們的API中的關(guān)系通過使用主鍵來表示。在本教程的這一部分中,我們將改進(jìn)API的內(nèi)聚力和可發(fā)現(xiàn)性,而不是使用超鏈接來進(jìn)行關(guān)系。

為我們的API的根創(chuàng)建一個端點

現(xiàn)在我們有'snippets'和'users'的端點,但是我們的API沒有一個入口點。要創(chuàng)建一個,我們將使用一個常規(guī)的基于函數(shù)的視圖和@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)

????})

這里應(yīng)該注意兩件事情。首先,我們使用REST框架的reverse功能來返回完全限定的URL;?第二,URL模式是通過方便的名稱來識別的,我們稍后會在此聲明snippets/urls.py。

為突出顯示的片段創(chuàng)建端點

我們的pastebin API中仍然缺少的另一個明顯的事情是代碼突出顯示端點。

與所有其他API端點不同,我們不想使用JSON,而只是呈現(xiàn)HTML表示。REST框架提供了兩種HTML渲染器樣式,一種用于處理使用模板呈現(xiàn)的HTML,另一種用于處理預(yù)呈現(xiàn)的HTML。第二個渲染器是我們要用于此端點的渲染器。

在創(chuàng)建代碼高亮度視圖時,我們需要考慮的另一件事是,我們可以使用現(xiàn)有的具體通用視圖。我們不是返回一個對象實例,而是一個對象實例的屬性。

而不是使用具體的通用視圖,我們將使用基類來表示實例,并創(chuàng)建我們自己的.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中創(chuàng)建的新視圖。我們將為我們的新API根添加一個url模式snippets/urls.py:

url(r'^$',?views.api_root),

然后為代碼片段添加一個url模式:

url(r'^snippets/(?P[0-9]+)/highlight/$',?views.SnippetHighlight.as_view()),

超鏈接我們的API

處理實體之間的關(guān)系是Web API設(shè)計中更具挑戰(zhàn)性的方面之一。我們可以選擇代表關(guān)系的一些不同的方式:

使用主鍵

在實體之間使用超鏈接。

在相關(guān)實體上使用唯一的標(biāo)識字段。

使用相關(guān)實體的默認(rèn)字符串表示形式。

將相關(guān)實體嵌套在父表示內(nèi)。

一些其他自定義表示。

REST框架支持所有這些樣式,并且可以將它們應(yīng)用于正向或反向關(guān)系,也可以在諸如通用外鍵之類的自定義管理器上應(yīng)用。

在這種情況下,我們希望在實體之間使用超鏈接樣式。為了這樣做,我們將修改我們的序列化程序來擴展HyperlinkedModelSerializer而不是現(xiàn)有的ModelSerializer。

在HyperlinkedModelSerializer有以下區(qū)別ModelSerializer:

id默認(rèn)情況下不包括該字段。

它包括一個url字段,使用HyperlinkedIdentityField。

關(guān)系使用HyperlinkedRelatedField,而不是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')

請注意,我們還添加了一個新的'highlight'字段。該字段與url字段的類型相同,只是它指向'snippet-highlight'url模式,而不是'snippet-detail'url模式。

因為我們已經(jīng)包括格式后綴的URL'.json',所以我們還需要在highlight字段上指出任何格式后綴的超鏈接它應(yīng)該使用'.html'后綴。

確保我們的URL模式被命名

如果我們要有一個超鏈接的API,我們需要確保我們命名我們的URL模式。我們來看看我們需要命名的URL模式。

我們的API的根源是指'user-list'和'snippet-list'。

我們的片段序列化程序包括一個引用的字段'snippet-highlight'。

我們的用戶串行器包括一個引用的字段'snippet-detail'。

我們的片段和用戶序列化程序包括'url'默認(rèn)情況下將引用的字段,'{model_name}-detail'在這種情況下將是'snippet-detail'和'user-detail'。

將所有這些名字添加到我們的URLconf中后,我們的最終snippets/urls.py文件應(yīng)該如下所示:

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[0-9]+)/$',

????????views.SnippetDetail.as_view(),

????????name='snippet-detail'),

????url(r'^snippets/(?P[0-9]+)/highlight/$',

????????views.SnippetHighlight.as_view(),

????????name='snippet-highlight'),

????url(r'^users/$',

????????views.UserList.as_view(),

????????name='user-list'),

????url(r'^users/(?P[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')),

]

添加分頁

用戶和代碼段的列表視圖可能會返回相當(dāng)多的實例,因此我們希望確保分頁結(jié)果,并允許API客戶端逐步瀏覽每個單獨的頁面。

我們可以通過tutorial/settings.py稍微修改我們的文件來更改默認(rèn)列表樣式來使用分頁。添加以下設(shè)置:

REST_FRAMEWORK?=?{

????'PAGE_SIZE':?10

}

請注意,REST框架中的設(shè)置都命名為單個字典設(shè)置,名為“REST_FRAMEWORK”,這有助于保持與其他項目設(shè)置的良好分離。

我們也可以自定義分頁風(fēng)格,如果我們也需要,但在這種情況下,我們將堅持默認(rèn)。

瀏覽API

如果我們打開瀏覽器并導(dǎo)航到可瀏覽的API,那么您將發(fā)現(xiàn)您現(xiàn)在可以通過以下鏈接了解API的方法。

您還可以在代碼段實例上看到“突出顯示”鏈接,這將使您轉(zhuǎn)到突出顯示的代碼HTML表示。

在本教程的第6部分中,我們將介紹如何使用ViewSets和路由器來減少構(gòu)建API所需的代碼量。s

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內(nèi)容