<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 什么是restful * REST與技術無關,代表的是一種軟件架構風格,REST是Representational State Transfer的簡稱,中文翻譯為“表征狀態轉移” * REST從資源的角度類審視整個網絡,它將分布在網絡中某個節點的資源通過URL進行標識,客戶端應用通過URL來獲取資源的表征,獲得這些表征致使這些應用轉變狀態 * 所有的數據,不過是通過網絡獲取的還是操作(增刪改查)的數據,都是資源,將一切數據視為資源是REST區別與其他架構風格的最本質屬性 * 對于REST這種面向資源的架構風格,有人提出一種全新的結構理念,即:面向資源架構(ROA:Resource Oriented Architecture) ## 什么是API 1、什么是API? 答:API就是接口,提供的url。接口有兩個用途: * \- 為別人提供服務 * \- 前后端分離,一個寫vue,一個寫后端,他們之間都是通過ajax請求 ## restful API設計規范 * API與用戶的通信協議,總是使用HTTPS協議。 * 域名? * https://api.example.com? ? ? ? ? ? ? ? ? ? ? ? ?盡量將API部署在專用域名(會存在跨域問題) * https://example.org/api/? ? ? ? ? ? ? ? ? ? ? ? API很簡單 * 版本 * URL,如:https://api.example.com/v1/ * 請求頭? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 跨域時,引發發送多次請求 * 路徑,視網絡上任何東西都是資源,均使用名詞表示(可復數) * https://api.example.com/v1/zoos * https://api.example.com/v1/animals * https://api.example.com/v1/employees * method * GET? ? ? :從服務器取出資源(一項或多項) * POST? ? :在服務器新建一個資源 * PUT? ? ? :在服務器更新資源(客戶端提供改變后的完整資源) * PATCH? :在服務器更新資源(客戶端提供改變的屬性) * DELETE :從服務器刪除資源 * 過濾,通過在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:指定篩選條件 * 狀態碼 ``` 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 - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。 ``` * 錯誤處理,狀態碼是4xx時,應返回錯誤信息,error當做key。 ~~~ { error: "Invalid API key" } ~~~ * 返回結果,針對不同操作,服務器向用戶返回的結果應該符合以下規范。 ~~~ GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔 ~~~ * Hypermedia API,RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什么。 ## 基于Django實現restful api 參考博客:https://www.cnblogs.com/wusir66/p/10016584.html ## 基于Django Rest Framework框架實現 PS:以下介紹的使用方式都是一些常用的,還有一些方式使用較少,在此不做介紹。 ### 一、自定義用戶認證   在models.py的UserInfo表中創建一些數據 ``` 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) models.py ``` ``` 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) view.py ```   在app目錄下創建一個rest\_utils的文件夾 ``` 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 auth.py(具體認證代碼) ```   配置文件 ~~~ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES':['app.rest_utils.auth.MyAuthentication',], } ~~~ 如果有某些類不需要使用認證,可以在類中加上以下代碼 ~~~ 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方法做分發 **1、對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方法,不然會報錯。** **2、加工完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異常 ``` **3、執行get/post/delete等方法** **4、對返回結果在進行加工** ### 二、自定義權限   在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 permission.py ```   配置文件 ~~~ 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]) throttle.py ```   配置文件 ~~~ 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) views.py ``` ### 五、解析器   配置文件 ~~~ REST_FRAMEWORK = { "DEFAULT_PARSER_CLASSES": ['rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser'] } ~~~   視圖函數中可以直接通過request.data拿到解析之后的數據 ### 六、序列化 序列化共有兩個功能:1、數據序列化? 2、請求數據校驗   數據序列化 ``` 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) models.py建表 ``` ``` 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) # +++++++++++++++++++++++++++++++++++++++++ views.py ``` ``` 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'), ] urls.py ```   請求數據校驗 ``` 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('提交數據') views.py ``` ~~~ from django.conf.urls import url from app.views import * urlpatterns = [ url('usergroup/$',UserGroupView.as_view()), ] ~~~ ### 七、分頁 PS:先自定義一個序列化,然后在分頁程序中導入這個序列化程序,所有的原生分頁需要現在settings.py中定義一下每頁顯示幾條數據 ~~~ REST_FRAMEWORK = { "PAGE_SIZE":2, } ~~~ A1、分頁,看第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 views.py ``` A2、分頁,看第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 views.py ``` 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 views.py ``` 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 views.py ``` 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 views.py ``` 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 views.py ``` ### 八、視圖   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) views.py ```   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) views.py ``` ~~~ 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 views.py ``` ~~~ 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 views.py ``` ``` 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'})), ] urls.py ``` 繼承關系: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'})), ] urls.py ```   這時候我們可以使用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)), ] urls.py ``` ### 十、渲染器   只需要在配置文件中配置一下所需要的渲染器類型就可以了 ~~~ REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES":[ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', ] } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看