一 。 restful python
restful 没有语言限制,django
一切皆资源:json
经过 请求方式知道要作什么操做 好比(HTTP GET、POST、PUT( 全局更新)/PATCH( 局部更新)、DELETE,还可能包括 HEADER 和 OPTIONS。)后端
restful (是一种协议,) 一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件能够更简洁,更有层次,更易于实现缓存等机制。api
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
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数据