1. 程式人生 > >API(五)之Relationships & Hyperlinked APIs

API(五)之Relationships & Hyperlinked APIs

settings logout amp 用戶 識字 cts for -s cnblogs

目前,我們的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

HyperlinkedModelSerializerModelSerializer有以下區別:

  • 默認情況下不包括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