• Django-Rest-Framework 教程: 5. 提高关联性和超链接API


    到目前为止, API之间的关系是以主键形式体现的, (比如打开/users/1/, 可以看到snippets中为snippet的主键). 在本篇中, 我们将使用超链接的形式, 进一步提高API的关联程度和可发现性. 首先我们补充一些路径, 是整个API结构更为完整.

    1. 根路径

    现在, 我们已经有了users和snippets的路径, 但对于API本身却没有一个根路径. 我们使用@api_view修饰器来创建一个function based view作为根路径:

        # snippets/views.py
        from rest_framework import renderers
        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)
            })

    注意, 我们使用了django-rest-framework的reverse(), 而不是django自带的reverse(), 此时如果打开http://127.0.0.1/8000, 会报错, 因为我们还没有为url添加name, 稍后我们会添加.

    在urls.py中添加对应的路径:

        # snippets/urls.py
        url(r'^$', views.api_root),

    2. 高亮snippet路径

    我们还需要提供高亮snippet的路径. 当然这一路径与其他不同, 我们希望使用HTML而不是JSON来呈现. Django-rest_framework为我们提供了两种方式呈现HTML, 一种是使用模板, 另一种则是已构建好的HTML文本. 由于在创建snippet时, 我们已经使用pygments将高亮的snippet转化为HTML文本储存在数据库中, 我们使用第二种方式.

    由于我们返回的并不是一个object实例, 而是一个实例的某个属性, django-rest-framework没有提供该generic class based view. 因此我们需要使用基本的view, 并创建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)

    在urls.py中添加对应的路径:

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

    3. 使用超链接

    处理各部件API之间的关系是一件头痛的事. django-rest_framework为我们提供了以下这些方法来表现关系:

    • 使用主键
    • 使用超链接
    • 使用相关项的slug field
    • 使用相关项的默认文本信息
    • 将子项显示在母项中
    • 其他表现方式

    这次, 我们使用超链接的方式来体现user和snippet的关系. 为了实现这一方式, 我们需要改写序列器(serializers), 使用HyperlinkedModelSerializer代替原本的ModelSerializer. HyperlinkedModelSerializer相对于ModelSerializer具有以下不同:

    • HyperlinkedModelSerializer不会自动包含pk field
    • HyperlinkedModelSerializer会自动包括url field
    • 关系使用的是HyperlinkedRelatedField而不是PrimaryKeyRelatedField
        # snippets/serializers.py
        class SnippetSerializer(serializers.HyperlinkedModelSerializer):
            owner = serializers.Field(source='owner.username')
            highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
    
            class Meta:
                model = Snippet
                fields = ('url', 'highlight', 'owner',
                          'title', 'code', 'linenos', 'language', 'style')
    
    
        class UserSerializer(serializers.HyperlinkedModelSerializer):
            snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail')
    
            class Meta:
                model = User
                fields = ('url', 'username', 'snippets')

    注意, 我们同时添加了 “highlight” field, 它与url field使用的一样, 是HyperlinkedRelatedField, 但指向的是snippet-highlight url而不是snippet-detail url.

    由于我们在url中包含了格式信息, 我们使用format=’html’参数为highlight指定.html后缀.

    4. 为url添加name

    编辑snippets/urls.py如下:

        # snippets/urls.py
        # API 路径
        urlpatterns = format_suffix_patterns(patterns('snippets.views',
            url(r'^$', '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 += patterns('',
            url(r'^api-auth/', include('rest_framework.urls',
                                       namespace='rest_framework')),
        )

    5. 分页

    如果数据库中的数据达到一定程度, 那么用户使用api时可能会返回大量数据, 因此, 我们最好使用分页功能:

    我们可以使用django-rest-framework自带的设置选项, 使list自动使用分页:

        # tutorial/settings.py
        REST_FRAMEWORK = {
            'PAGINATE_BY': 10
        }

    6. 测试

    现在可以使用之前提到的方法测试我们的API了, 可以在/snippets/中看到, 原先的id已经被url代替, url和highlight field都采用超链接的形式.

    原文链接: http://www.weiguda.com/blog/23/

  • 相关阅读:
    opengl编程指南
    Binder机制1---Binder原理介绍
    [Android]使用platform密钥来给apk文件签名的命令
    IntentFilter
    最高分是多少
    Spring注入
    Bean容器的初始化
    Spring中的Junit
    IOC
    接口及面向接口编程
  • 原文地址:https://www.cnblogs.com/leo23/p/5051919.html
Copyright © 2020-2023  润新知