一、什么是API?html
答:API就是接口,提供的url。接口有两个用途:vue
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 - [*]:服务器发生错误,用户将没法判断发出的请求是否成功。
{
error: "Invalid API key"
}
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
参考博客:https://www.cnblogs.com/wusir66/p/10016584.htmlpython
PS:如下介绍的使用方式都是一些经常使用的,还有一些方式使用较少,在此不作介绍。ajax
在models.py的UserInfo表中建立一些数据django
from django.db import models class UserInfo(models.Model): user_type_choices = ( (1,'普通用户'), (2,'VIP'), (3,'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) class UserToken(models.Model): user = models.OneToOneField(to='UserInfo') token = models.CharField(max_length=64)
from django.http import JsonResponse from rest_framework.views import APIView from app.models import * import hashlib import time #建立token字符串 def md5(user): ctime = str(time.time()) m = hashlib.md5(bytes(user,encoding='utf-8')) m.update(bytes(ctime,encoding='utf-8')) return m.hexdigest() #找到指定用户给其token值 class AuthView(APIView): authentication_classes = [] def post(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: name = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = UserInfo.objects.filter(username=name,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' token = md5(name) UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '请求异常' return JsonResponse(ret) #利用token值来进行认证 class OrderView(APIView): def get(self,request,*args,**kwargs): ret = {'code':1000,'msg':None,'data':None} order = {'goods':'food'} try: ret['data'] = order except Exception as e: ret['msg'] = '有问题' return JsonResponse(ret)
在app目录下建立一个rest_utils的文件夹json
from rest_framework.authentication import BaseAuthentication from app.models import * from rest_framework import exceptions class MyAuthentication(BaseAuthentication): def authenticate(self, request): token = request._request.GET.get('token') obj = UserToken.objects.filter(token=token).first() if not obj: raise exceptions.AuthenticationFailed('用户未认证') return (obj.user,obj) def authenticate_header(self, request): pass
配置文件后端
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES':['app.rest_utils.auth.MyAuthentication',], }
若是有某些类不须要使用认证,能够在类中加上如下代码api
authentication_classes = []
源码大体流程跨域
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进行加工(添加数据) 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 # 第三步、执行:get/post/put/delete函数 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方法作分发
一、对request进行加工(添加数据)
a、首先 request = self.initialize_request(request, *args, **kwargs)点进去,会发现:在Request里面多加了四个,以下
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(), #解析数据,默认的有三种方式,可点进去看 #self.get_authenticator优先找本身的,没有就找父类的 authenticators=self.get_authenticators(), #获取认证相关的全部类并实例化,传入request对象供Request使用 negotiator=self.get_content_negotiator(), parser_context=parser_context )
b、获取认证相关的类的具体 authenticators=self.get_authenticators()
def get_authenticators(self): """ Instantiates and returns the list of authenticators that this view can use. """ #返回的是对象列表 return [auth() for auth in self.authentication_classes] #[SessionAuthentication,BaseAuthentication]
c、查看认证的类:self.authentication_classes
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES #默认的,若是本身有会优先执行本身的
d、接着走进api_settings
api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) #点击继承的DEFAULTS类 DEFAULTS类 DEFAULTS = { # Base API policies 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', #这时候就找到了他默认认证的类了,能够导入看看 'rest_framework.authentication.BasicAuthentication' ),
e、导入了类看看类里面具体干了什么
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import BaseAuthentication
f、看到里面有个authenticate方法和authenticate_header方法
class BaseAuthentication(object): """ All authentication classes should extend BaseAuthentication. """ def authenticate(self, request): """ Authenticate the request and return a two-tuple of (user, token). """ raise NotImplementedError(".authenticate() must be overridden.") def authenticate_header(self, request): """ Return a string to be used as the value of the `WWW-Authenticate` header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ pass
具体处理认证,从headers里面能获取用户名和密码
class BasicAuthentication(BaseAuthentication): """ HTTP Basic authentication against username/password. """ www_authenticate_realm = 'api' def authenticate(self, request): """ Returns a `User` if a correct username and password have been supplied using HTTP Basic authentication. Otherwise returns `None`. """ auth = get_authorization_header(request).split() if not auth or auth[0].lower() != b'basic': return None #返回none不处理。让下一个处理 if len(auth) == 1: msg = _('Invalid basic header. No credentials provided.') raise exceptions.AuthenticationFailed(msg) elif len(auth) > 2: msg = _('Invalid basic header. Credentials string should not contain spaces.') raise exceptions.AuthenticationFailed(msg) try: auth_parts = base64.b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(':') #用partition切割冒号也包括 except (TypeError, UnicodeDecodeError, binascii.Error): msg = _('Invalid basic header. Credentials not correctly base64 encoded.') raise exceptions.AuthenticationFailed(msg) userid, password = auth_parts[0], auth_parts[2] # 返回用户和密码 return self.authenticate_credentials(userid, password, request) def authenticate_credentials(self, userid, password, request=None): """ Authenticate the userid and password against username and password with optional request for context. """ credentials = { get_user_model().USERNAME_FIELD: userid, 'password': password } user = authenticate(request=request, **credentials) if user is None: raise exceptions.AuthenticationFailed(_('Invalid username/password.')) if not user.is_active: raise exceptions.AuthenticationFailed(_('User inactive or deleted.')) return (user, None) def authenticate_header(self, request): return 'Basic realm="%s"' % self.www_authenticate_realm
g、固然restfulframework默认定义了两个类。咱们也能够自定制类,本身有就用本身的了,本身没有就去找父类的了,可是里面必须实现authenticate方法,否则会报错。
二、加工完request以后的操做
认证流程
a、首先 self.initial(request, *args, **kwargs)能够看到作了如下操做
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. #2.1 处理版本信息 version, scheme = self.determine_version(request, *args, **kwargs) request.version, request.versioning_scheme = version, scheme # Ensure that the incoming request is permitted #2.2 认证 self.perform_authentication(request) # 2.3 权限 self.check_permissions(request) # 2.4 请求用户进行访问频率的限制 self.check_throttles(request)
b、咱们先来看认证,self.perform_authentication(request) 具体干了什么,按住ctrl点击进去
def perform_authentication(self, request): """ Perform authentication on the incoming request. Note that if you override this and simply 'pass', then authentication will instead be performed lazily, the first time either `request.user` or `request.auth` is accessed. """ request.user #执行request的user,这是的request已是加工后的request了
c、那么咱们能够从视图里面导入一下Request,找到request对象的user方法
from rest_framework.views import Request
@property def user(self): """ Returns the user associated with the current request, as authenticated by the authentication classes provided to the request. """ if not hasattr(self, '_user'): with wrap_attributeerrors(): self._authenticate() # return self._user #返回user
d、执行self._authenticate() 开始用户认证,若是验证成功后返回元组: (用户,用户Token)
def _authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. """ #循环对象列表 for authenticator in self.authenticators: try: #执行每个对象的authenticate 方法 user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple #返回一个元组,user,和auth,赋给了self, # 只要实例化Request,就会有一个request对象,就能够request.user,request.auth了 return self._not_authenticated()
e、在user_auth_tuple = authenticator.authenticate(self) 进行验证,若是验证成功,执行类里的authenticatie方法
f、若是用户没有认证成功:self._not_authenticated()
def _not_authenticated(self): """ Set authenticator, user & authtoken representing an unauthenticated request. Defaults are None, AnonymousUser & None. """ #若是跳过了全部认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None # if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户AnonymousUser else: self.user = None # None 表示跳过该认证 if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN() # 默认值为:None else: self.auth = None # (user, token) # 表示验证经过并设置用户名和Token; # AuthenticationFailed异常
三、执行get/post/delete等方法
四、对返回结果在进行加工
在app目录下建立一个rest_utils的文件夹
from rest_framework.permissions import BasePermission class MyPermission(BasePermission): message = '必须是svip才能访问' def has_permission(self,request,view): if request.user.user_type != 3: return False return True
配置文件
REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': ['app.rest_utils.permission.MyPermission', ], }
若是有某些类不须要使用权限,能够在类中加上如下代码
permission_classes = []
在app目录下建立一个rest_utils的文件夹
from rest_framework.throttling import BaseThrottle import time VISIT_RECORD = {} class VisitThrottle(BaseThrottle): def __init__(self): self.history = None def allow_request(self,request,view): # 1. 获取用户IP remote_addr = self.get_ident(request) 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 # return True # 表示能够继续访问 # return False # 表示访问频率过高,被限制 def wait(self): # 还须要等多少秒才能访问 ctime = time.time() return 60 - (ctime - self.history[-1])
配置文件
REST_FRAMEWORK = { "DEFAULT_THROTTLE_CLASSES": ["app.rest_utils.throttle.VisitThrottle"], }
若是有某些类不须要使用节流,能够在类中加上如下代码
throttle_classes = []
配置文件
REST_FRAMEWORK = { "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", "DEFAULT_VERSION":'v1', "ALLOWED_VERSIONS":['v1','v2'], "VERSION_PARAM":'version', }
路由
from django.conf.urls import url from app.views import * urlpatterns = [ url('^(?P<version>[v1|v2]+)/orderview/$',OrderView.as_view(),name='wusir'), ]
视图
from django.http import JsonResponse from rest_framework.views import APIView from app.models import * import hashlib import time def md5(user): ctime = str(time.time()) m = hashlib.md5(bytes(user,encoding='utf-8')) m.update(bytes(ctime,encoding='utf-8')) return m.hexdigest() class AuthView(APIView): authentication_classes = [] permission_classes = [] def post(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: name = request._request.POST.get('username') pwd = request._request.POST.get('password') obj = UserInfo.objects.filter(username=name,password=pwd).first() if not obj: ret['code'] = 1001 ret['msg'] = '用户名或密码错误' token = md5(name) UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['token'] = token except Exception as e: ret['code'] = 1002 ret['msg'] = '请求异常' return JsonResponse(ret) class OrderView(APIView): def get(self,request,*args,**kwargs): ret = {'code':1000,'msg':None,'data':None} order = {'goods':'food'} # 得到版本信息 print(request.version) # 获取处理版本的对象 print(request.versioning_scheme) #反向生成url(rest_framework) u1 = request.versioning_scheme.reverse(viewname='wusir',request=request) print(u1) try: ret['data'] = order except Exception as e: ret['msg'] = '有问题' return JsonResponse(ret)
配置文件
REST_FRAMEWORK = { "DEFAULT_PARSER_CLASSES": ['rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser'] }
视图函数中能够直接经过request.data拿到解析以后的数据
序列化共有两个功能:一、数据序列化 二、请求数据校验
数据序列化
from django.db import models class UserGroup(models.Model): title = models.CharField(max_length=32) class UserInfo(models.Model): user_type_choices = ( (1,'普通用户'), (2,'VIP'), (3,'SVIP'), ) user_type = models.IntegerField(choices=user_type_choices) username = models.CharField(max_length=32,unique=True) password = models.CharField(max_length=64) group = models.ForeignKey("UserGroup") roles = models.ManyToManyField("Role") class UserToken(models.Model): user = models.OneToOneField(to='UserInfo') token = models.CharField(max_length=64) class Role(models.Model): title = models.CharField(max_length=32)
import json from rest_framework.views import APIView from django.http import HttpResponse from rest_framework import serializers from app.models import * #========================================= # 自定义序列化类一 class RolesSerializers(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() class RoleViews(APIView): def get(self,request,*args,**kwargs): # 方式一 ,没有使用数据序列化 res = Role.objects.all().values('title') res = list(res) res = json.dumps(res,ensure_ascii=False) # 方式二 ,序列化多个数据[obj,obj,obj] res = Role.objects.all() ser = RolesSerializers(instance=res,many=True) res = json.dumps(ser.data,ensure_ascii=False) # 方式三 ,序列化单个数据 [obj] res = Role.objects.all().first() ser = RolesSerializers(instance=res,many=False) res = json.dumps(ser.data,ensure_ascii=False) return HttpResponse(res) # ========================================= # +++++++++++++++++++++++++++++++++++++++++ # 自定义序列化类二 class UserInfoSerializers(serializers.Serializer): # user_type = serializers.IntegerField() aaaaa = serializers.IntegerField(source='user_type') bbbbb = serializers.CharField(source='get_user_type_display') username = serializers.CharField() password = serializers.CharField() gps = serializers.CharField(source='group.id') # rls = serializers.CharField(source='roles.all') # 用这个拿到的是一个一个的对象 rls = serializers.SerializerMethodField() # 自定义显示 def get_rls(self,row): obj_list = row.roles.all() ret = [] for i in obj_list: ret.append({'id':i.id,'title':i.title}) return ret # 自定义序列化类三 class UserInfoSerializers(serializers.ModelSerializer): bbbbb = serializers.CharField(source='get_user_type_display') group = serializers.CharField(source='group.title') rls = serializers.SerializerMethodField() def get_rls(self,row): obj_list = row.roles.all() ret = [] for i in obj_list: ret.append({'id':i.id,'title':i.title}) return ret class Meta: model = UserInfo # fields = '__all__' fields = ['id','username','password','bbbbb','group','rls'] # 自定义序列化类四(深度化控制) class UserInfoSerializers(serializers.ModelSerializer): class Meta: model = UserInfo # fields = '__all__' fields = ['id','username','password','user_type','group','roles'] depth = 1 # 自定义序列化类五(Hypermedia API) class UserInfoSerializers(serializers.ModelSerializer): group = serializers.HyperlinkedIdentityField(view_name='wusir',lookup_field='group_id',lookup_url_kwarg='pk') class Meta: model = UserInfo # fields = '__all__' fields = ['id','username','password','user_type','group','roles'] class UserInfoViews(APIView): def get(self,request,*args,**kwargs): users = UserInfo.objects.all() ser = UserInfoSerializers(instance=users,many=True,context={'request':request}) res = json.dumps(ser.data,ensure_ascii=False) return HttpResponse(res) # GroupSerializers和GroupViews配合自定义序列化类五生成Hypermedia API后,点击url能够看详情 class GroupSerializers(serializers.ModelSerializer): class Meta: model = UserGroup fields = '__all__' class GroupViews(APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') res = UserGroup.objects.filter(id=pk).first() ser = GroupSerializers(instance=res,many=False) res = json.dumps(ser.data,ensure_ascii=False) return HttpResponse(res) # +++++++++++++++++++++++++++++++++++++++++
from django.conf.urls import url from app.views import * urlpatterns = [ url('role/$',RoleViews.as_view()), url('info/$',UserInfoViews.as_view()), url('group/(?P<pk>\d+)$',GroupViews.as_view(),name='wusir'), ]
请求数据校验
class XXValidator(object): def __init__(self, base): self.base = base def __call__(self, value): if not value.startswith(self.base): message = '标题必须以 %s 为开头。' % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): pass class UserGroupSerializer(serializers.Serializer): title = serializers.CharField(error_messages={'required': '标题不能为空'},validators=[XXValidator('wusir'),]) # required为错误时的提示信息,validators为自定义验证器,能够自定义功能,也能够不写,不写的话只能校验数据是否为空 class UserGroupView(APIView): def post(self, request, *args, **kwargs): ser = UserGroupSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data['title']) else: print(ser.errors) return HttpResponse('提交数据')
from django.conf.urls import url from app.views import * urlpatterns = [ url('usergroup/$',UserGroupView.as_view()), ]
PS:先自定义一个序列化,而后在分页程序中导入这个序列化程序,全部的原生分页须要如今settings.py中定义一下每页显示几条数据
REST_FRAMEWORK = { "PAGE_SIZE":2, }
A一、分页,看第n页,每页显示n条数据(原生)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import PageNumberPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = PageNumberPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
A二、分页,看第n页,每页显示n条数据(自定义)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import PageNumberPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class MyPageNumberPagination(PageNumberPagination): page_size = 3 #默认每页显示个数 page_query_param = 'page' #get传参表示第几页 page_size_query_param = 'pagesize' #get传参表示每页显示几个 max_page_size = 5 #每页最大显示个数 class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = MyPageNumberPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
B1. 分页,在n个位置,向后查看n条数据(原生)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import LimitOffsetPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = LimitOffsetPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
B2. 分页,在n个位置,向后查看n条数据(自定义)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import LimitOffsetPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 3 #默认每页显示个数 limit_query_param = 'limit' #get传参表示每页显示个数 offset_query_param = 'offset' #get传参表示跳过几个数据显示 max_limit = 6 #每页最大显示个数 class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = MyLimitOffsetPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
C1.加密分页,上一页和下一页(原生)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import CursorPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = CursorPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
C2.加密分页,上一页和下一页(自定义)
from django.http import JsonResponse, HttpResponse from rest_framework.pagination import CursorPagination from rest_framework.views import APIView from app.models import * import hashlib import time from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response class MyCursorPagination(CursorPagination): cursor_query_param = 'wusir' #get参数中肯定以什么值为key来接受下一页的参数 page_size = 3 #默认每页显示数目 ordering = 'id' #根据什么字段来进行排序 page_size_query_param = 'pagesize' #get传参表示每页显示几个 max_page_size = 5 #每页最大显示数目 class PageView(APIView): authentication_classes = [] permission_classes = [] throttle_classes = [] def get(self,request,*args,**kwargs): roles = Role.objects.all() pg = MyCursorPagination() page_roles = pg.paginate_queryset(queryset=roles,request=request,view=self) ser = PagerSerialiser(instance=page_roles,many=True) # return Response(ser.data) return pg.get_paginated_response(ser.data) #页面上加上上下页的url
PS:View和APIView在此处就很少介绍
GenericAPIView
from rest_framework.pagination import PageNumberPagination from rest_framework.views import APIView from app.models import * from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.response import Response from rest_framework.generics import GenericAPIView class View1View(GenericAPIView): authentication_classes = [] permission_classes = [] throttle_classes = [] queryset = Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def get(self,request,*args,**kwargs): # 获取数据 roles = self.get_queryset() # 分页 pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles,many=True) return Response(ser.data)
GenericViewSet(as_view里面能够用字典的方式让get,post等不一样的方法对应执行不一样名称的函数)
from rest_framework.pagination import PageNumberPagination from app.models import * from rest_framework.response import Response from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet class View1View(GenericViewSet): authentication_classes = [] permission_classes = [] throttle_classes = [] queryset = Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination def list(self, request, *args, **kwargs): # 获取数据 roles = self.get_queryset() # 分页 pager_roles = self.paginate_queryset(roles) # 序列化 ser = self.get_serializer(instance=pager_roles, many=True) return Response(ser.data)
from django.conf.urls import url from app.views import * urlpatterns = [ url(r'^view1view/$',View1View.as_view({'get':'list'})), ]
mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,
(任意举两个栗子)
from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import GenericViewSet,ModelViewSet from rest_framework.mixins import ListModelMixin,CreateModelMixin class View1View(GenericViewSet,ListModelMixin,CreateModelMixin): authentication_classes = [] permission_classes = [] throttle_classes = [] queryset = Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination
from django.conf.urls import url from app.views import * urlpatterns = [ url(r'^view1view/$',View1View.as_view({'get':'list','post':'create'})), ]
ModelViewSet
from app.rest_utils.serializsers.pager import PagerSerialiser from rest_framework.viewsets import ModelViewSet class View1View(ModelViewSet): authentication_classes = [] permission_classes = [] throttle_classes = [] queryset = Role.objects.all() serializer_class = PagerSerialiser pagination_class = PageNumberPagination
from django.conf.urls import url from app.views import * urlpatterns = [ url(r'^view1view/$',View1View.as_view({'get': 'list','post':'create'})), url(r'^view1view/(?P<pk>\d+)/$',View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), ]
继承关系:APIView继承了View,GenericAPIView继承了APIView,GenericViewSet继承了GenericAPIView和ViewSetMixin,ModelViewSet继承了mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin和GenericViewSet。
当继承了ModelViewSet以后,一个视图对于的完整的路由就有如下四种
from django.conf.urls import url from app.views import * urlpatterns = [ # http://127.0.0.1:8000/api/v1/v1/?format=json url(r'^(?P<version>[v1|v2]+)/view1view/$', View1View.as_view({'get': 'list','post':'create'})), # http://127.0.0.1:8000/api/v1/v1.json url(r'^(?P<version>[v1|v2]+)/view1view\.(?P<format>\w+)$', View1View.as_view({'get': 'list','post':'create'})), url(r'^(?P<version>[v1|v2]+)/view1view/(?P<pk>\d+)/$', View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), url(r'^(?P<version>[v1|v2]+)/view1view/(?P<pk>\d+)\.(?P<format>\w+)$', View1View.as_view({'get': 'retrieve','delete':'destroy','put':'update','patch':'partial_update'})), ]
这时候咱们可使用rest_framework给咱们自动生成路由的方式来生成以上四种路由,效果相同
from django.conf.urls import url, include from app.views import * from rest_framework import routers router = routers.DefaultRouter() router.register(r'view1view',View1View) urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/', include(router.urls)), ]
只须要在配置文件中配置一下所须要的渲染器类型就能够了
REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES":[ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ] }