python - Django - restframework 簡單使用 和 組件

FBV 和 CBV前端

CBV 經過函數調用方法
FBV 經過類調用方法
    其本質上都是 CBV
可是 FBV 內部封裝了關於 method 的方法,因爲基本上都是前端的請求,全部像GET,POST等方法用的頻繁,
而CBV將這些方法封裝了起來,使得開發時更便捷了許多,因此CBV更適合寫接口

######  標準的  ######
2.1 fbv方式請求的過程

用戶發送url請求,Django會依次遍歷路由映射表中的全部記錄,一旦路由映射表其中的一條匹配成功了,
就執行視圖函數中對應的函數名,這是fbv的執行流程

2.2 cbv方式請求的過程

當服務端使用cbv模式的時候,用戶發給服務端的請求包含url和method,這兩個信息都是字符串類型

服務端經過路由映射表匹配成功後會自動去找dispatch方法,而後Django會經過dispatch反射的方式找到類中對應的方法並執行

類中的方法執行完畢以後,會把客戶端想要的數據返回給dispatch方法,由dispatch方法把數據返回經客戶端

數據庫

 

一:下載django

pip install djangorestframewrok

 

二:Viewsjson

# restframework 經常使用的類
from rest_framework.views import APIView from rest_framework.generics import GenericAPIView from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import ModelViewSet from rest_framework.response import Response

寫法1:session

--
    from rest_framework import serializers (1)和 models 表中的字段對應 (使用模塊:serializers.Serializer) (2)所有字段直接寫(使用模塊:serializers.ModelSerializer) class Meta: model = models.Book fields = '__all__' (3)使用時須要調用 BookModelSerializers(queryset/data,many=True/False) 注:當須要返回一個 queryset 的時候必須加 many=True 這個參數,單條數據則不用 --
 ----------Url----------
 from app01 import views re_path('book/$',views.BookView.as_view()) ----------View----------
from rest_framework import serializers class BookModelSerializers(serializers.ModelSerializer): title = serializers.CharField() price = serializers.CharField() publish = serializers.CharField() from rest_framework.views import APIView from rest_framework.views import Response # 更新操做:
def put(self,request,pk): shop = models.Shop.objects.filter(pk=pk).first() bs = ShopSerializers(shop,data=request.data) if bs.is_valid():   # 判斷數據是否有誤
        print('bs: ',bs) bs.save() # 至關於調用了 updata方法
    return Response(bs.data)    # 返回 數據
    else: return Response(bs.errors) # 添加操做:
ps = PublishSerializers(data=request.data) if ps.is_valid(): ps.save() # create

# 查詢操做:
class BookView(APIView): def get(self,request): book_list = models.Book.objects.all() serializers = BookModelSerializers(book_list,many=True) return Response(serializers.data) # 刪除操做:
def delete(self,request,pk): models.Shop.objects.filter(pk=pk).delete() return Response()

 

寫法2:app

-- (a) (1)mixins 模塊中有 List,Create,Put...方法能夠直接使用 (2)generics 主要做用仍是調用 APIView 中的 --

----------Url----------
 from app01 import views re_path('book/$',views.BookView.as_view()) ----------View (a)---------- 
from rest_framework import mixins from rest_framework import generics from rest_framework import serializers from rest_framework import serializers class BookModelSerializers(serializers.ModelSerializer): title = serializers.CharField() price = serializers.CharField() publish = serializers.CharField() class AuthorView(mixins.ListModelMixin,generics.GenericAPIView): queryset = models.Author.objects.all()      # 必須有的參數 :queryset
    serializer_class = AuthorModelSerializers   # 必須有的參數 :serializer_class

    def get(self,request,*args,**kwargs): return self.list(request,*args,**kwargs) -- (b) (1)繼承 generics.RetrieveUpdateDestroyAPIView 將上面的 mixins generics 所有封裝成了一個模塊 --

 ----------View (b)---------- 比上面簡單一點 class UserView(generics.RetrieveUpdateDestroyAPIView): queryset = models.User.objects.all() serializer_class = UserModelSerializers

 

寫法三:dom

-- (1) as_view({參數}) 中傳的參數是必須的,參數的名稱仍是固定的, 可根據需求來限定哪一個url配定哪一個參數 (2) view 中 的變量名也是固定的,不能改變, 當執行到某個父類的方法的時候,就會須要這兩個參數 queryset -- queryset serializer_class --
----------Url----------
from app01 import views re_path('book/$', views.Book.as_view({'get': 'list', 'post': 'create'})), re_path('book/(?P<pk>\d+)/$', views.Book.as_view({'get': 'retrieve', 'put': 'update','delete':'destroy'})), ----------View----------

from rest_framework import viewsets class Book(viewsets.ModelViewSet): queryset = models.Book.objects.all() serializer_class = BookModelSerializers

 

四:認證組件ide

----------  View(局部認證)  ----------
-- (1) BaseAuthentication 模塊中 有倆個方法(authenticate , authenticate_header) 注:這倆個方法也是固定名字,兩個必須寫上,一個都不能少,不然報錯 ! 模塊中這兩個方法都是返回空的,可是執行的時候當前函數就將 兩個方法覆蓋了,也就是少些一個 authenticate_header (2) 建立一個 返回 隨機字符的 token (3) update_or_create -- 若是有就更新,若是沒有就建立 --

# 認證 組件
from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication from app01 import models class TokenAuth(BaseAuthentication): # 這個方法直接寫在一個文件中 def authenticate(self,request): token = request.GET.get('token')  # 獲取 token
        token_obj = models.Token.objects.filter(token=token).first()  # 驗證 token 是否匹配
        if not token_obj: raise exceptions.AuthenticationFailed('驗證失敗') else: return token_obj.user.name,token_obj.token # 返回一個 登錄校驗判斷 的隨機字符串
def get_random_str(user): import hashlib,time ctime = str(time.time())    # 當前時間字符串
 md5 = hashlib.md5(bytes(user,encoding='utf8'))  # md5 加密,加鹽
    md5.update(bytes(ctime,encoding='utf8'))        # 將字符串進行拼接

    #md5.digest() 二進制
    #md5.hexdigest() 十六進制
    return md5.hexdigest()  # 返回一個 十六進制 的加密隨機字符

# 登錄驗證
class LoginView(APIView): authentication_classes = [TokenAuth]  
    def post(self,request): name = request.data.get('name')    # 獲取用戶名
        pwd = request.data.get('pwd')    # 獲取密碼
        user = models.User.objects.filter(name=name,pwd=pwd).first()  # 數據庫校驗
        res = {'code':0,'msg':None} if user: random_str = get_random_str(user.name) token = models.Token.objects.update_or_create(user=user,defaults={'token':random_str}) # 在數據庫生成 token
            res['token'] = random_str res['code'] = 1 res['msg'] = '驗證成功'
        else: res['msg'] = '驗證失敗'
        import json return Response(json.dumps(res)) ----------  View(全局認證)  ---------- (1) settings 中配置 認證組件位置: # 全局認證組件
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",] } (2) 這樣就不用寫 authentication_classes = [TokenAuth] (3) 若是哪一個方法不須要認證的話 只須要 authentication_classes = [] 將列表設爲空

 

五:權限組件函數

# 權限組件
class SvipPermission(object):  # 這個方法直接寫在一個文件中 message = "只有超級用戶才能訪問"
    def has_permission(self,request,view): username = request.user user_type = models.User.objects.filter(name=username).first().user_type if user_type == 3: return True     # 返回True 則驗證經過
        else: return False    # 返回False 則驗證不經過

# 只需類下面添加
permission_classes = [SvipPermission] # 權限組件 -- 局部

# 全局認證
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES":['app01.utils.SvipPermission'], # 全局權限組件
}

 

六:解析器 (用於將解析字符格式)post

 

from rest_framework.parsers import JSONParser,FormParser parser_classes = [JSONParser, FormParser]  # 局部 (用於將解析字符格式)

 

七:頻率組件:

 - 自定義:

# 定義一個頻率認證類 - 以後在視圖配置
import time from rest_framework.throttling import BaseThrottle class MyThrottle(BaseThrottle): visited_record = {} def __init__(self): self.history = None def allow_request(self, request, my_cbv): # 這個my_cbv是源碼中傳的咱們的視圖類,這裏咱們也要傳進去
        # print(self.get_ident(request)) # 能夠獲取本次請求的ip
        ip = request.META.get("REMOTE_ADDR") if ip not in self.visited_record: self.visited_record[ip] = [] current_time = time.time() history = self.visited_record[ip] self.history = history print(history) while history and current_time - history[-1] > 60:  # 把大於60秒的時間都刪掉
 history.pop() if len(history) > 2:  # 第三次訪問,列表中只有2個值,也知足條件
            return False history.insert(0, current_time) return True def wait(self): """ 用於返回還剩多少時間訪問; 本次訪問時間:9:50:55 [09:50:30, 09:50:20, 09:50:10] 剩餘 60 - (9:50:55 - 09:50:10)秒才能訪問 :return: """ c_time = time.time() return 60 - (c_time - self.history[-1]) #### 局部使用 ####
from rest_framework import generics from rest_framework import mixins from app01.utils.frequency import MyThrottle class ListView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin): throttle_classes = [MyThrottle] def get(self, request, *args, **kwargs): return Response('ok') #### 全局使用 ####
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ), 'DEFAULT_THROTTLE_CLASSES': ( 'app01.utils.frequency.MyThrottle', ), } 

 

 - 內置

#### 定義類 ####
from rest_framework.throttling import SimpleRateThrottle class MyThrottle(SimpleRateThrottle): scope = "visit_rate"  # 這個值決定了在配置時使用那個變量描述限制的頻率

    def get_cache_key(self, request, view):  # 這個方法也是必需要有
        return self.get_ident(request) #### 只能在全局使用 ####
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': ( 'app01.utils.throttle_class.MyThrottle', ), "DEFAULT_THROTTLE_RATES": { "visit_rate": "10/m", # 這個參數就是頻率類中定義的那個參數scope, 其中第一個數字10表示10次,後面的m表示一分鐘,還有s,一秒, h, 一小時, d, 一天
 } }

 

 

八:分頁器 -- 用於 restframework 內置的調試頁面

# 要使用 restframework 自帶的調試數據網頁 須要在 settings 中配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework',  # 配置 restframework 組件
]


#
分頁器 from rest_framework.pagination import PageNumberPagination class BookPageNumberPagination(PageNumberPagination): page_size = 1 # 每頁顯示個數 page_query_param = 'page' page_size_query_param = 'size' # 修改當前頁顯示個數 #max_page_size = 2 # 每頁顯示個數限制 class BookView(APIView): def get(self,request): book_list = models.Book.objects.all() # 分頁器 pnp = BookPageNumberPagination() book_page = pnp.paginate_queryset(book_list,request,self) bs = BookModelSerializers(book_page,many=True,context={'request': request}) return Response(bs.data)
相關文章
相關標籤/搜索