1. 程式人生 > >python - Django - restframework 簡單使用 和 組件

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

n) nbsp tle false 方式 price led char dom

FBV 和 CBV

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

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

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

2.2 cbv方式請求的過程

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


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

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

一:下載

pip install djangorestframewrok

二:Views

    # 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:

--
    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:

--
(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

寫法三:

--
    (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

四:認證組件

----------  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‘], # 全局權限組件
}

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

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

七:分頁器 -- 用於調試 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)

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