zoukankan      html  css  js  c++  java
  • 6,视图和路由

    REST framework includes an abstraction for dealing with ViewSets, that allows the developer to concentrate on modeling the state and interactions of the API, and leave the URL construction to be handled automatically, based on common conventions.

    ViewSet classes are almost the same thing as View classes, except that they provide operations such as read, or update, and not method handlers such as get or put.

    A ViewSet class is only bound to a set of method handlers at the last moment, when it is instantiated into a set of views, typically by using a Router class which handles the complexities of defining the URL conf for you.

    REST 包含一个抽象的类 ViewSets, 允许开发者专注于模型和 API 的交互, 基于常见协议自动创建 URL。

    ViewSet 类集 几乎与 View 类一样,提供像 read ,update的操作, get put ....

    一个 ViewSet 类只是在最后阶段绑定到方法,

    Refactoring to use ViewSets

    Let's take our current set of views, and refactor them into view sets.

    First of all let's refactor our UserList and UserDetail views into a single UserViewSet. We can remove the two views, and replace them with a single class:

    使用 viewset 重构视图函数。

    首先把UserList 和 UserDetail 视图都写到 UserViewSet,这样我们可以用一个视图函数去取代之前的两个。

    from rest_framework import viewsets
    
    class UserViewSet(viewsets.ReadOnlyModelViewSet):
        """
        This viewset automatically provides `list` and `detail` actions.
        """
        queryset = User.objects.all()
        serializer_class = UserSerializer

    Here we've used ReadOnlyModelViewSet class to automatically provide the default 'read-only' operations. We're still setting the queryset and serializer_class attributes exactly as we did when we were using regular views, but we no longer need to provide the same information to two separate classes.

    这里,我们使用 ReadOnlyModelViewSet 类来自动提供 ‘read-only’ 操作。 我们仍然要提供 queryset 和 serializer_class 属性,但是不用像之前那样同样的内容出现在两个类中。

    Next we're going to replace the SnippetList, SnippetDetail and SnippetHighlight view classes. We can remove the three views, and again replace them with a single class.

    接下来,我们用一个类去取代 SnippetList,SnippetDetail 和 SnippetHighlight 三个类。

    from rest_framework.decorators import link
    
    class SnippetViewSet(viewsets.ModelViewSet):
        """
        This viewset automatically provides `list`, `create`, `retrieve`,
        `update` and `destroy` actions.
    
        Additionally we also provide an extra `highlight` action.
        """
        queryset = Snippet.objects.all()
        serializer_class = SnippetSerializer
        permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                              IsOwnerOrReadOnly,)
    
        @link(renderer_classes=[renderers.StaticHTMLRenderer])
        def highlight(self, request, *args, **kwargs):
            snippet = self.get_object()
            return Response(snippet.highlighted)
    
        def pre_save(self, obj):
            obj.owner = self.request.user

    This time we've used the ModelViewSet class in order to get the complete set of default read and write operations.

    Notice that we've also used the @link decorator to create a custom action, named highlight. This decorator can be used to add any custom endpoints that don't fit into the standard create/update/delete style.

    Custom actions which use the @link decorator will respond to GET requests. We could have instead used the @action decorator if we wanted an action that responded to POST requests.

    这次,我们使用 ModelViewSet 类是为了得到完整的  read ,write 方法。

    注意,我们也使用了 @link 装饰器来创建一个自定义行为,名为  highlight。这个装饰器可以用来添加任何哪些不适合标准的  create/update/delete 方法的自定义端点。

    使用 @link 的自定义行为回应 GET 请求,如需要回应 POST 请求可以使用 @action 装饰器。

    Binding ViewSets to URLs explicitly

    The handler methods only get bound to the actions when we define the URLConf. To see what's going on under the hood let's first explicitly create a set of views from our ViewSets.

    当我们使用 URLConf , 处理方法只是绑定到行为。为了看到内部原理,我们第一次在 ViewSets 中显示地创建一些视图。

    In the urls.py file we bind our ViewSet classes into a set of concrete views.

    在 urls.py 文件中,我们绑定我们的 ViewSet 类 到视图上。

    from snippets.views import SnippetViewSet, UserViewSet
    from rest_framework import renderers
    
    snippet_list = SnippetViewSet.as_view({
        'get': 'list',
        'post': 'create'
    })
    snippet_detail = SnippetViewSet.as_view({
        'get': 'retrieve',
        'put': 'update',
        'patch': 'partial_update',
        'delete': 'destroy'
    })
    snippet_highlight = SnippetViewSet.as_view({
        'get': 'highlight'
    }, renderer_classes=[renderers.StaticHTMLRenderer])
    user_list = UserViewSet.as_view({
        'get': 'list'
    })
    user_detail = UserViewSet.as_view({
        'get': 'retrieve'
    })

    Notice how we're creating multiple views from each ViewSet class, by binding the http methods to the required action for each view.

    注意我们是怎样从每个 ViewSet 类中创建多个视图的,我们是通过绑定  http 方式到每个视图当中的。

    Now that we've bound our resources into concrete views, that we can register the views with the URL conf as usual.

    现在我们绑定我们的视图函数到 urlconf 中,我们像之前那样在  URL conf 中注册我们的视图函数。

    urlpatterns = format_suffix_patterns(patterns('snippets.views',
        url(r'^$', 'api_root'),
        url(r'^snippets/$', snippet_list, name='snippet-list'),
        url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'),
        url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
        url(r'^users/$', user_list, name='user-list'),
        url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail')
    ))
     

    Using Routers

    Because we're using ViewSet classes rather than View classes, we actually don't need to design the URL conf ourselves. The conventions for wiring up resources into views and urls can be handled automatically, using a Router class. All we need to do is register the appropriate view sets with a router, and let it do the rest.

    因为我们使用 ViewSet 类而不是 View 类, 我们实际上可以不用自己设计 URL Conf。使用 Router 类,这些都可以自动完成。 我们只需通过一个 router 注册我们的视图函数。

    Here's our re-wired urls.py file.

    重写 urls.py 文件:

    from django.conf.urls import patterns, url, include
    from snippets import views
    from rest_framework.routers import DefaultRouter
    
    # Create a router and register our viewsets with it.
    router = DefaultRouter()
    router.register(r'snippets', views.SnippetViewSet)
    router.register(r'users', views.UserViewSet)
    
    # The API URLs are now determined automatically by the router.
    # Additionally, we include the login URLs for the browseable API.
    urlpatterns = patterns('',
        url(r'^', include(router.urls)),
        url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
    )

    Registering the viewsets with the router is similar to providing a urlpattern. We include two arguments - the URL prefix for the views, and the viewset itself.

    The DefaultRouter class we're using also automatically creates the API root view for us, so we can now delete the api_root method from our views module.

    用 router 注册 viewsets 类似于提供一个 urlpattern。我们包含两个参数:URL 前缀 和 viewsets。

    使用DefaultRouter 类可以帮我们自动生成 API 根视图,我们现在可以从我们的视图模块中删除 api_root 方法。

    Trade-offs between views vs viewsets

    Using viewsets can be a really useful abstraction. It helps ensure that URL conventions will be consistent across your API, minimizes the amount of code you need to write, and allows you to concentrate on the interactions and representations your API provides rather than the specifics of the URL conf.

    使用 viewsets 是一个非常有用的抽象。它帮我们确保 URL 与 API 一致, 减少我们的代码量,也让我们专注在交互和 提供的API 上,而不是 URL conf的细节。

    That doesn't mean it's always the right approach to take. There's a similar set of trade-offs to consider as when using class-based views instead of function based views. Using viewsets is less explicit than building your views individually.

    这并不意味那是正确常用的方法,它是使用基于类和基于函数的视图函数间的权衡。使用 viewsets 会是视图变得不是那么清晰。

    Reviewing our work

    With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browseable, and comes complete with authentication, per-object permissions, and multiple renderer formats.

    通过很少的代码,我们现在得到了一系列完整的 Web API,这些API可以通过浏览器使用,具有完整的权限控制,有多种的渲染格式。

    We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.

    You can review the final tutorial code on GitHub, or try out a live example in the sandbox.

    Onwards and upwards

    We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here's a few places you can start:

  • 相关阅读:
    [PHP] class_exists类不存在时会调用__autoload函数
    [Redis] Redis的消息机制- 发布订阅
    [发电] 现在正式入驻爱发电平台
    [MySQL] PHP IP登录限制的实现
    [Redis] 哈希表的Rehash机制
    [Redis] redis的hash类型底层结构哈希表
    [Linux] ls命令的几个常用参数实现按时间/文件大小排序
    [Go] 在gin框架gorm下查询一对多的数据
    [Redis] list底层的数据结构
    [GO]go redis实现滑动窗口限流-redis版
  • 原文地址:https://www.cnblogs.com/nigang/p/3758909.html
Copyright © 2011-2022 走看看