restful 和 restframework

 一 。 restful   python

  restful  没有语言限制,django

     一切皆资源:json

      经过 请求方式知道要作什么操做 好比(HTTP GET、POST、PUT( 全局更新)/PATCH( 局部更新)、DELETE,还可能包括 HEADER 和 OPTIONS。)后端

  restful (是一种协议,) 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件能够更简洁,更有层次,更易于实现缓存等机制。api

  

RESTful的实现:RESTful Web 服务与 RPC 样式的 Web 服务
了解了什么是REST,咱们再看看RESTful的实现。使用 RPC 样式架构构建的基于 SOAP 的 Web 服务成为实现 SOA 最经常使用的方法。RPC 样式的 Web 服务客户端将一个装满数据的信封(包括方法和参数信息)经过 HTTP 发送到服务器。服务器打开信封并使用传入参数执行指定的方法。方法的结果打包到一个信封并做为响应发回客户端。客户端收到响应并打开信封。每一个对象都有本身独特的方法以及仅公开一个 URI 的 RPC 样式 Web 服务,URI 表示单个端点。它忽略 HTTP 的大部分特性且仅支持 POST 方法。
 
 
二    CBA (View)的请求流程
def as_view(cls, **initkwargs): """ Main entry point for a request-response process. """
        for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__)) if not hasattr(cls, key): raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key)) def view(request, *args, **kwargs): self = cls(**initkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) view.view_class = cls view.view_initkwargs = initkwargs # take name and docstring from class
        update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=()) return view

 

  1.项目加载 执行 as_view() 函数浏览器

  2. as_view() 本身没有找父类(View)去要缓存

  3.as_view方法, return 一个函数名(view) view函数在as_view方法里面   服务器

  4. 服务端接收玩一个请求才 执行view方法restful

  4. 执行view函数 返回一个 return self.dispatch(request, *args, **kwargs) 架构

  5. dispatch函数

    看你什么请求执行对应的函数

    def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        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 return handler(request, *args, **kwargs)

三  用rest_framework 组件, 要在 INSTALLED_APPS 中配置中加一句

   "rest_frameword"

 

 四.  APIView的请求流程;

   1. APIView  继承 View类

  2. 项目加载执行APIView 中的有as_view 方法, 返回的是一个它父类的(View) view 函数 等待用户发送请求方式调用

   4 .用户 发送一个GET请求到后端, 走url(r'^books/', views.BookDetailView.as_view()), 执行View 函数

  5. view中 as_view执行view函数 返回一个 return self.dispatch(request, *args, **kwargs) 

  6.dispatch方法APIView本身有因此就用本身的 

  7. dispatch中的 

     request = self.initialize_request(request, *args, **kwargs)

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 ) class Request(object): """ Wrapper allowing to enhance a standard `HttpRequest` instance. Kwargs: - request(HttpRequest). The original request instance. - parsers_classes(list/tuple). The parsers to use for parsing the request content. - authentication_classes(list/tuple). The authentications used to try authenticating the request's user. """

    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

 

      self.request = request

 

 8. 在BookDetailView中调用:
    request._request.GET 就是 request.GET
    jango 中为了方便
request._request.GET 能够简写为 request.GET
 

 五  rest_framework中的ModelViewSet  视图

  ps:由于有两个GET请求,若是还用之前的执行请求的方式,就不行了,就要用ModelViewSet ,

 把请求方式设为KEY,对应不一样的Value函数名,就解决了这个问题。

  能够简便的实现restful协议的查(查看所有数据),增,单一的改,查,删  

   视图代码

from rest_framework.viewsets import ModelViewSet class AuthorsModelView(ModelViewSet): queryset = Author.objects.all() serializer_class = AuthorModelSerializers

  url 路径代码

from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 五个功能用同一个类
    url(r'^book/$',views.AuthorsModelView.as_view({"get": "list", "post": "create"})), url(r"^book/(?P<pk>\d+)/$", views.AuthorsModelView.as_view({ "get": "retrieve", "put": "update", "delete": "destroy", })) ]

(1) ModelViewSet继承了五个类源码pass

class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): """ A viewset that provides default `create()`, `retrieve()`, `update()`, `partial_update()`, `destroy()` and `list()` actions. """
    pass

(2) 项目加载执行as_view()函数,

(3) as_view() 本身没有找父类(GenericViewSet,GenericViewSet父类ViewSetMixin中有一个 as_view方法),返回一个view函数名

(4)等服务器收到一个请求在执行view函数吧参数传给action这个默认参数接收,吧参数字典循环出来,经过steattr操做 后面执行

请求函数就是以后它的Value函数,

(5) Value 对应的函数在继承的 这五个类中 

              mixins.CreateModelMixin,

 mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin,

  六 。 rest_framework  认证组件 请求流程  

 ·

    1. 认证组件继承APIView,APIView   继承 View类

   2. 项目加载执行APIView 中的有as_view 方法, 返回的是一个它父类的(View) view 函数 等待用户发送请求方式调用

   3. 用户发送请求到服务端,执行view方法, view方法中调用dispatch方法,APIView有用APIView的,

  4 APIView 在分发请求以前 执行 self.initial(request, *args, **kwargs)

  5.self.initial(request, *args, **kwargs)  调用这个方法执行这个方法中的认证组件你方法 self.perform_authentication(request) 

  6. self.perform_authentication(request)方法中调用 request.user 这个静太方法

  7. 找这个request.user 在self.initialize_request(request, *args, **kwargs) 方法中的Request的类中,执行request.user方法,在这个方法中调用Request的类中 self._authenticate(self)  方法

8._authenticate 这类中循环一个for authenticator in self.authenticators:
9.self.authenticators 是self.authenticators = authenticators or () 赋的值
10.authenticators 是 调用Request 这个类中传的参数
  
Request( request, parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context )

11.self.get_authenticators() 这个方法 的返回值赋值给 authenticators,调用 get_authenticators() 这个方法返回的是一个列表推到式   return [auth() for auth in self.authentication_classes] 

12 authentication_classes 就是你本身写的想要认证的类  对应的是视图中的 authentication_classes = [ "写本身想要认证的类" ]

13. 因此 第八步骤_authenticate 这类中循环一个for authenticator in self.authenticators: 循环的 是你本身想要认证的类循环中 user_auth_tuple = authenticator.authenticate(self) 调用authenticate(self)  , authenticate(self)  方法 视图中有所及就执行、

 14. 执行视图中的 authenticate(self) , 必须返回两个值,源码才能收到,或者 抛出异常 保持根源吗一致

15 。authentication_classes 作了哪些操做才能接收你想要认证的类。

ps , 在项目settings 中加一个

    REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":(
    "app01.service.auth.AuthUser",
    )
    }

16 api_settings.DEFAULT_AUTHENTICATION_CLASSES执行这个方法, api_settings,中根本没有DEFAULT_AUTHENTICATION_CLASSES方法, 可是有def __getattr__(self, attr) 方法, attr 就是DEFAULT_AUTHENTICATION_CLASSES, 走到 if attr not in self.defaults:   self.defaults】不是空不符合if条件 接着走val =   self.user_settings   [attr] 拆开来看, 而后 调用user_settings方法

17. 执行user_settings方法, user_settings方法,  self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})找本身在settings中设置的值,找不到返回一个空字典,

18, 把返回值赋值给  valsetattr(self, attr, val)   之后再调用DEFAULT_AUTHENTICATION_CLASSES  就是调用"app01.service.auth.AuthUser     return val 返还给 api_settings.DEFAULT_AUTHENTICATION_CLASSES 再赋值authentication_classes 之后这个app下的表都认证就能够了

class AuthorsModelView(ModelViewSet):


    authentication_classes = [ "写本身想要认证的类" ]

    queryset = Author.objects.all()
    serializer_class = AuthorModelSerializers



################################---Login----############################

from app01.models import User,UserToken

def get_random_str(user):

    import hashlib,time
    ctime=str(time.time())

    md5=hashlib.md5(bytes(user,encoding="utf8"))
    md5.update(bytes(ctime,encoding="utf8"))

    return md5.hexdigest()




from django.http import JsonResponse

class LoginViewSet(APIView):

    def post(self,request,*args,**kwargs):
        res={"code":200,"msg":None}
        try:
            user=request.data.get("user")
            pwd=request.data.get("pwd")
            user_obj=User.objects.filter(name=user,pwd=pwd).first()
            print(user,pwd,user_obj)
            if not user_obj:
                res["code"]=405
                res["msg"]="用户名或者密码错误"
            else:
                token=get_random_str(user)
                UserToken.objects.update_or_create(user=user_obj,defaults={"token":token})
                res["token"]=token

        except Exception as e:
            res["code"]=1002
            res["msg"]=e

        return JsonResponse(res,json_dumps_params={"ensure_ascii":False})

关于认证的总结:
1 认证失败,抛异常
2 认证成功:
若是是最后一次认证,返回元组,若是不是,返回None。

   

             七  ,权限组件和频率组件 和认证组件 大致相同 

1. 权限代码
   在app01.service.permissions.py中:
    
from rest_framework.permissions import BasePermission class SVIPPermission(BasePermission): message="SVIP才能访问!"
    def has_permission(self, request, view): if request.user.user_type==3: return True return False

    在views.py:

from app01.service.permissions import *

class BookViewSet(generics.ListCreateAPIView): permission_classes = [SVIPPermission,] queryset = Book.objects.all() serializer_class = BookSerializers

settings.py配置以下:

  

REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",] }

        2 。 频率组件代码


在app01.service.throttles.py中:
from rest_framework.throttling import BaseThrottle VISIT_RECORD={} class VisitThrottle(BaseThrottle): def __init__(self): self.history=None def allow_request(self,request,view): remote_addr = request.META.get('REMOTE_ADDR') print(remote_addr) import time ctime=time.time() if remote_addr not in VISIT_RECORD: VISIT_RECORD[remote_addr]=[ctime,] return True history=VISIT_RECORD.get(remote_addr) self.history=history while history and history[-1]<ctime-60: history.pop() if len(history)<3: history.insert(0,ctime) return True else: return False def wait(self): import time ctime=time.time() return 60-(ctime-self.history[-1])

 

  在views.py:

 
from app01.service.permissions import *

class BookViewSet(generics.ListCreateAPIView): permission_classes = [SVIPPermission,] queryset = Book.objects.all() serializer_class = BookSerializers
 

settings.py配置以下:

REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",], "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",], "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",] # 频率组件 }
 八. rest_framework 中的URL 路由
from rest_framework import routers from app01 import views routers=routers.DefaultRouter() routers.register("authors",views.AuthorsModelView) routers.register("publishes",views.PublishModelView) routers.register("books",views.BookModelView) urlpatterns = [ url(r'^admin/', admin.site.urls), # url(r'^index/',index),
    url(r"^",include(routers.urls)),

           九.  rest_framework中的分页

  简单分页 比较经常使用

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class PNPagination(PageNumberPagination): page_size = 1 page_query_param = 'page' page_size_query_param = "size" max_page_size = 5

class BookViewSet(viewsets.ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializers def list(self,request,*args,**kwargs): book_list=Book.objects.all() pp=LimitOffsetPagination() pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self) print(pager_books) bs=BookSerializers(pager_books,many=True) #return Response(bs.data)
        return pp.get_paginated_response(bs.data)

    偏移分页

from rest_framework.pagination import LimitOffsetPagination
 
 

        十. 解析器

request类

  jango的request类和rest-framework的request类的源码解析

局部视图

  (通常默认就能够)

from rest_framework.parsers import JSONParser,FormParser
class PublishViewSet(generics.ListCreateAPIView):
    parser_classes = [FormParser,JSONParser]
    queryset = Publish.objects.all()
    serializer_class = PublshSerializers
    def post(self, request, *args, **kwargs):
        print("request.data",request.data)
        return self.create(request, *args, **kwargs)

全局视图

复制代码
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
    "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
    "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
    "DEFAULT_THROTTLE_RATES":{
        "visit_rate":"5/m",
    },
    "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',]
}

 

        十一.   响应器 

 1. 不写用默认便可  

from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer class BookView(APIView): renderer_classes = [JSONRenderer]

若是是浏览器访问就返回HTML页面,若是不是就返回一个JSon数据
相关文章
相关标签/搜索