zoukankan      html  css  js  c++  java
  • RESTful

    什么是RESTful?

    RESTful(Representational State Transfer)与技术无关,它是一种设计风格,中文翻译为‘表征状态转移’,所有的数据,无论是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质的属性。

    对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)。

    RESTful规范

    1.路径,视网络上的任何东西都是资源,均使用名词表示(可为复数)。

    eg:https://127.0.0.1:8080/books/

    2.method,通过请求方式的不同,进行不同的操作。

    127.0.0.1/books/  get请求:表示获取所有图书   从服务器取出资源(一项或多项)
    127.0.0.1/books/1  get请求:表示获取id为1的图书   
    127.0.0.1/books/  post请求:表示新增一本书   在服务器新建一个资源
    127.0.0.1/books/  delete请求:表示删除一本书   从服务器删除资源
    127.0.0.1/books/  put/patch请求:表示修改一本书   在服务器更新资源

    3.API与用户的通信协议,总是使用HTTPs协议(它是加密的协议)。

    4.域名

    #https://api.baidu.com    尽量将API部署在专用域名(会存在跨域问题)
    
    #https://127.0.0.1:8080/api/  API很简单

    5.版本

    #URL,eg: https://api.baidu.com/v1/
    
    #可以写在请求头中   跨域时会引发多次请求

    6.过滤,通过在url上传参的形式传递搜索条件

    #https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
    #https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
    #https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
    #https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    #https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件

    7.状态码

    1开头:服务器正在处理

    2开头:服务器处理成功

    3开头:重定向

    4开头:客户端错误

    5开头:服务器错误

    #200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    #201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    #202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    #204 NO CONTENT - [DELETE]:用户删除数据成功。
    #400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    #401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    #403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    #404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    #406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    #410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    #422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    #500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

    8.错误处理,应返回错误信息,error当作key。

    9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范:

    GET/collection:返回资源对象的列表(数组)
    GET/collection/resource:返回单个资源对象
    POST/collection:返回新生成的资源对象
    PUT/collection/resource:返回完整的资源对象
    PATCH/collection/resource:返回完整的资源对象
    DELETE/collection/resource:返回一个空文档

    10.返回结果中提供链接

    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}

    CBV(View)的源代码执行流程:

    #1.路由写成:url(r'^books/', views.Books.as_view()),
    #2.当程序启动,views.Books.as_view()其实已经是一个函数的内存地址了(as_view()执行的结果,返回的就是view函数对象);
    #3.发送请求,as_view()执行,就是view(request,*args,**kwargs)执行,内部的dispatch(request,*args,**kwargs)执行;
    #4.dispatch方法内部通过请求方式(get,post),反射出要执行的方法,去执行,然后返回

    APIView

    1.安装djangorestframework

    #方式1:pip3 install djangorestframework
    #方式2:pycharm图形化界面安装
    #方式3:pycharm命令行下安装(装在当前工程所用的解释器下)

    本质上就是一个app,要在配置文件settings.py中注册该app: 'rest_framework'。

    2.djangorestframework的APIView分析

    执行时,as_view()执行内部dispatch方法就是APIView自己内部的dispatch方法了。

    @classmethod
        def as_view(cls, **initkwargs):
            """
            Store the original class on the view function.
    
            This allows us to discover information about the view when we do URL
            reverse lookups.  Used for breadcrumb generation.
            """
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    raise RuntimeError(
                        'Do not evaluate the `.queryset` attribute directly, '
                        'as the result will be cached and reused between requests. '
                        'Use `.all()` or call `.get_queryset()` instead.'
                    )
                cls.queryset._fetch_all = force_evaluation
    
            view = super(APIView, cls).as_view(**initkwargs)
            view.cls = cls
            view.initkwargs = initkwargs
    
            # Note: session based authentication is explicitly CSRF validated,
            # all other authentication is CSRF exempt.
            return csrf_exempt(view)
    as_view方法
    def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                self.initial(request, *args, **kwargs)
    
                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                response = self.handle_exception(exc)
    
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response
    dispatch方法
     def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
    initalize_request
    def initial(self, request, *args, **kwargs):
            """
            Runs anything that needs to occur prior to calling the method handler.
            """
            self.format_kwarg = self.get_format_suffix(**kwargs)
    
            # Perform content negotiation and store the accepted info on the request
            neg = self.perform_content_negotiation(request)
            request.accepted_renderer, request.accepted_media_type = neg
    
            # Determine the API version, if versioning is in use.
            version, scheme = self.determine_version(request, *args, **kwargs)
            request.version, request.versioning_scheme = version, scheme
    
            # Ensure that the incoming request is permitted
            # 认证
            self.perform_authentication(request)
            # 权限
            self.check_permissions(request)
            # 频率
            self.check_throttles(requ
    initial方法(内部调用认证、权限和频率)
    class Request(object):
        def __init__(self, request, parsers=None, authenticators=None,
                     negotiator=None, parser_context=None):
            assert isinstance(request, HttpRequest), (
                'The `request` argument must be an instance of '
                '`django.http.HttpRequest`, not `{}.{}`.'
                .format(request.__class__.__module__, request.__class__.__name__)
            )
    
            self._request = request
            self.parsers = parsers or ()
            self.authenticators = authenticators or ()
            self.negotiator = negotiator or self._default_negotiator()
            self.parser_context = parser_context
            self._data = Empty
            self._files = Empty
            self._full_data = Empty
            self._content_type = Empty
            self._stream = Empty
    
            if self.parser_context is None:
                self.parser_context = {}
            self.parser_context['request'] = self
            self.parser_context['encoding'] = request.encoding or settings.DEFAULT_CHARSET
    
            force_user = getattr(request, '_force_auth_user', None)
            force_token = getattr(request, '_force_auth_token', None)
            if force_user is not None or force_token is not None:
                forced_auth = ForcedAuthentication(force_user, force_token)
                self.authenticators = (forced_auth,)
    
    
        def __getattr__(self, attr):
            """
            If an attribute does not exist on this instance, then we also attempt
            to proxy it to the underlying HttpRequest object.
            """
            try:
                return getattr(self._request, attr)
            except AttributeError:
                return self.__getattribute__(attr)
    
        
    
        @property
        def data(self):
            if not _hasattr(self, '_full_data'):
                self._load_data_and_files()
            return self._full_data
    
    
        @property
        def FILES(self):
            # Leave this one alone for backwards compat with Django's request.FILES
            # Different from the other two cases, which are not valid property
            # names on the WSGIRequest class.
            if not _hasattr(self, '_files'):
                self._load_data_and_files()
            return self._files
    
    
        @property
        def query_params(self):
            """
            More semantically correct name for request.GET.
            """
            return self._request.GET
    Request对象
    
    
  • 相关阅读:
    事件基础
    Event loop 事件的循环和为什么使用函数
    Promise 对象---异步调用
    新版博客园分类不能正常显示
    OpenCV学习
    c# 常用正则
    C#调用OpenCV——美图效果
    WPF中的Image控件Source的设置(包括直接读取图片文件的代码)
    图像处理的灰度化和二值化
    C#弹出U盘
  • 原文地址:https://www.cnblogs.com/wangke0917/p/10594286.html
Copyright © 2011-2022 走看看