Django drf 關系和超鏈接API

2020-01-22 11:22 更新

目前我們的API中的關系是用主鍵表示的。我們將通過使用超鏈接來提高我們API的內(nèi)部聯(lián)系。

為我們的API創(chuàng)建一個根路徑

現(xiàn)在我們有'snippets'和'users'的路徑,但是我們的API沒有一個入口點。我們將使用一個常規(guī)的基于函數(shù)的視圖和我們前面介紹的@api_view裝飾器創(chuàng)建一個。在你的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功能來返回完全限定的URL;第二,URL模式是通過方便的名稱來標識的,我們稍后將在snippets/urls.py中聲明。

為高亮顯示的代碼片段創(chuàng)建路徑

我們的API中另一個明顯缺少的是代碼高亮顯示路徑。

與所有其他API路徑不同,我們不想使用JSON,而只是需要HTML表示。REST框架提供了兩種HTML渲染器,一種用于處理使用模板渲染的HTML,另一種用于處理預渲染的HTML。第二個渲染器是我們要用于此路徑的渲染器。

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

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

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

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

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

超鏈接我們的API

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

  • 使用主鍵。
  • 在實體之間使用超鏈接。
  • 在相關實體上使用唯一的標識字段。
  • 使用相關實體的默認字符串表示形式。
  • 將相關實體嵌套在父表示中。
  • 一些其他自定義表示。

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

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

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

  • 默認情況下不包括id字段。
  • 它包含一個url字段,使用HyperlinkedIdentityField。
  • 關聯(liá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字段上指出任何格式后綴的超鏈接,它應該使用'.html'后綴。

確保我們的URL模式被命名

如果我們要使用超鏈接的API,那么需要確保為我們的URL模式命名。我們來看看我們需要命名的URL模式。

  • 我們API的根路徑是指'user-list'和'snippet-list'。
  • 我們的代碼片段序列化器包含一個指向'snippet-highlight'的字段。
  • 我們的用戶序列化器包含一個指向'snippet-detail'的字段。
  • 我們的代碼片段和用戶序列化程序包括'url'字段,默認情況下將指向'{model_name}-detail',在這個例子中就是'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')
])

# 可瀏覽API的登錄和注銷視圖
urlpatterns += [
    url(r'^api-auth/', include('rest_framework.urls',
                               namespace='rest_framework')),
]

添加分頁

用戶和代碼片段的列表視圖可能會返回相當多的實例,因此我們希望確保對結(jié)果分頁,并允許API客戶端依次獲取每個單獨的頁面。

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

REST_FRAMEWORK = {
    'PAGE_SIZE': 10
}

請注意,REST框架中的所有設置都放在一個名為“REST_FRAMEWORK”的字典中,這有助于區(qū)分項目中的其他設置。

如果需要的話,我們也可以自定義分頁風格,但在這個例子中,我們將一直使用默認設置。

瀏覽API

如果我們打開瀏覽器并瀏覽我們的API,那么你可以簡單的通過頁面上的超鏈接來了解API。

你還可以看到代碼片段實例上的'highlight'鏈接,它能帶你跳轉(zhuǎn)到高亮顯示的代碼HTML表示。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號