zoukankan      html  css  js  c++  java
  • Django REST framework 第五章 Relationships & Hyperlinked APIs

    到目前为止,API内部的关系是使用主键来代表的。在这篇教程中,我们将提高API的凝聚力和可发现性,通过在相互关系上使用超链接。

    Creating an endpoint for the root of our API

    现在,我们已经有了snippets和users的终端,但是没有一个单独的终端指向我们的API。使用之前常规的FBV方式和@api_view装饰器创建一个。在你的app的views文件内

    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方法来返回完全合格的URLs;其次URL模式由稍后在app的urls文件内申明的便利的名称标识。

    Creating an endppoint for the highlighted snippets

    另一个明显的问题是在我们的API中仍然缺失代码突出的端点。

    不像之前写过的API端点,我们不想使用JSON,而是用网页的表现形式来替代。REST framework提供了2种风格的HTML转换,一种用于处理使用模板呈现的HTML,另一个用于处理预先呈现的HTML。第二种渲染器是我们愿意在这个端点使用的那个。

    另外还有一件事需要考虑, 当创建代码高亮视图时,没有我们可以使用的集成通用的视图。我们不会返回一个对象实例,取而代之的是一个对象实例的属性。

    展示实例我们将可以使用基础类代替集成通用的视图,然后创建get方法。在app的views文件中添加:

    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)

    跟之前一样,这里还需要添加新的URL跟视图绑定。为新的API根添加url模式在app内的urls文件中:

        path('', views.api_root),

    然后添加新的url模式:

        path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view()),

    Hyperlinking our API

    处理实体之间的关系是Web API设计中更具挑战性的方面之一。有很多不同的方式可供我们选择来表示这一关系。

    a、使用主键

    b、在实体间使用超链接

    c、在相关实体上使用唯一的标识字段

    d、使用相关实体的默认字符串表示形式

    e、将相关实体嵌套在父表示中

    f、一些其他的自定制的表示形式

    REST framework 支持所有这些方式,并且可以将它们应用于正向反向关系,或者自定制的管理(比如通用的外键)

    在这个事例中,我们更倾向于在实体间用超链接方式。为了能够实现,我们将要修改serializers来扩展HyperlinkedModelSerializer代替现有的ModelSerializer

    1、默认不包含id字段

    2、它包含一个url字段,使用HyperlinkedIdentityField

    3、关系用PrimaryKeyRelatedField代替HyperlinkedRelatedField

    用超链接可以很简单的重写已经存在的serializers,在app内的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'代替'snippet-detail'url模式。因为我们包含了格式化后缀的rul比如json,所以也需要在highlight字段上指出,它返回的任何格式化后缀的超链接都应该使用.html后缀。

    Making sure our URL patterns are named

    如果我们想要用超链接的API,需要确保ur已经命名。一起看一下那些url需要命名

    a、引用'user-list'和'snippet-list'的根API

    b、包含在snippet serializer中的一个字段引用'snippet-highlight'

    c、包含在user serializer中的一个字段引用'snippet-detail'

    d、默认的snippet和user serializers中包含url字段的,将引用'{model_name}-detail',在这个事例里将会是'snippet-detail''user-detail'

    将这些名称全部加入url配置后,最终app 内的urls文件应该是这样的:

    from app01 import views
    from django.urls import path, include
    from rest_framework.urlpatterns import format_suffix_patterns
    
    
    app_name = 'app01'
    urlpatterns = [
        path('snippets/', views.SnippetList.as_view(), name='snippet-list'),
        path('snippets/<int:pk>/', views.SnippetDetail.as_view(), name='snippet-detail'),
        path('users/', views.UserList.as_view(), name='user-list'),
        path('users/<int:pk>/', views.UserDetail.as_view(), name='user-detail'),
        path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view(), name='snippet-highlight'),
        path('', views.api_root),
    ]
    urlpatterns = format_suffix_patterns(urlpatterns)

    Adding pagination

    装有users和code的snippets的视图列表最终能返回许多实例,因此我们真的要确保对结果进行分页,允许的API客户端逐个遍历每一个独立的页面.

    可以该变默认的列表样式以使用分页,通过稍微修改app内的settings文件:

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 10
    }

    注意,REST framework中所有的设定都命名在一个独立的字典REST_FRAMEWORK里,它帮助我们跟其他项目的设置很好的分离开。

    如果必要的话,我们也可以定制分页形式,但在这个事例中只是处理默认的分页。

  • 相关阅读:
    设计模式之四(抽象工厂模式第二回合)
    C# try catch finally
    设计模式之三(工厂方法模式)
    C# XML与Json之间的相互转换
    Google免费的SVN服务器管理VS2010代码
    设计模式之四(抽象工厂模式第一回合)
    MVC项目开发中那些用到的知识点(Jquery ajax提交Json后台处理)
    设计模式之四(抽象工厂模式第三回合)
    设计模式之二(简单工厂模式)
    Jquery的$命名冲突
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/9462802.html
Copyright © 2011-2022 走看看