一、什麼是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', ] }