您好,登錄后才能下訂單哦!
一、CBV的源碼分析
-Class Base View(基于類的視圖)
-Function Base View(基于函數(shù)的視圖)
-def as_view 類方法
-def view:類方法內(nèi)部
閉包函數(shù)定義:內(nèi)層函數(shù)包含對外部作用域的引用
-python中一切皆對象:函數(shù)也是對象
-hasattr(self, 'get')--判斷self類中是不是有該(get)方法
-反射 setattr(self,get,get_all):相當(dāng)于把get函數(shù),變成了get_all
-getattr(self, 'get'):拿到get函數(shù)的內(nèi)存地址
# 執(zhí)行:dispatch:誰的dispatch方法?寫的cbv的那個c,視圖中的那個視圖類
# 我這個類如果沒有寫dispatch,會執(zhí)行View中的dispatch方法
return self.dispatch(request, *args, **kwargs)
與上方截圖是同一地方代碼。
下面作用:在路由選擇之前(urls.py),是走哪個請求(例如:'get','post'等),是由dispatch來決定的。
-def dispatch(self, request, *args, **kwargs): # request.method 前臺請求的方法,轉(zhuǎn)成了小寫 # http_method_names View中定義的一個列表:是一堆請求方式 if request.method.lower() in self.http_method_names: # http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] # getattr的第三個參數(shù)是默認(rèn)值:self.http_method_not_allowed # 拿到get方法的內(nèi)存地址 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed #get(request,*args, **kwargs) return handler(request, *args, **kwargs)
總結(jié):*******請求來了--->as_view---->view---->dispatch--->分發(fā)到不同的函數(shù),執(zhí)行函數(shù),拿到結(jié)果,然后返回
urls.py
# as_view(),是從View中繼承過來的,用類來調(diào)用的,它是一個類的方法。
# 如果是get請求,會影響到類內(nèi)部,執(zhí)行g(shù)et(或是post)方法
# View類內(nèi)部函數(shù)的內(nèi)存地址。(例如:get與post的函數(shù)重寫)
url(r'^login/', views.Test.as_view()),
views.py
from django.views import View class Test(View): def get(self,request,*args,**kwargs): print('get') return render(request,'login.html') def post(self,request): # 知道這里沒傳,所以沒寫,正常情況下要寫上-> def post(self,request,*args,**kwargs) name=request.POST.get('name') pwd=request.POST.get('pwd') if name=='user' and pwd=='123': return HttpResponse('successful') else: return render(request,'login.html',{'error':'用戶名密碼錯誤'})
templates/login.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="" method="post"> <p>用戶名:<input type="text" name="name"></p> <p>密碼:<input type="password" name="pwd"></p> <p><input type="submit" value="提交"><span>{{ error }}</span></p> </form> </body> </html>
訪問:http://127.0.0.1:8000/login/
登錄中是整個頁面刷新的,如果只是局部刷新的話,應(yīng)該用的是ajax提交的表單
閱讀源碼:(pycharm)
左側(cè)工程欄--->設(shè)置圖標(biāo)-->點擊--->show members(能看到py文件,類的方法)
二、resful規(guī)范(是什么)
- 是一個規(guī)范
- 面向資源編程:把網(wǎng)絡(luò)中所有東西,想象成資源
-規(guī)范:
-10條規(guī)范
1、-API與用戶的通信協(xié)議,總是使用HTTPs協(xié)議:https比http安全
2、-域名
https://api.example.com 盡量將API部署在專用域名(會存在跨域問題)
https://example.org/api/ API很簡單
例如寫一個查詢所有圖書的api接口:
https://api.example.com/books
https://127.0.0.1/api/books
3、版本:每個接口都應(yīng)該有版本
URL
如:https://api.example.com/v1/
https://127.0.0.1/api/v2/books(推薦用這種)
請求頭 跨域時,引發(fā)發(fā)送多次請求
4、路徑,視網(wǎng)絡(luò)上任何東西都是資源,均使用名詞表示(可復(fù)數(shù))
https://api.example.com/v1/books
https://api.example.com/v1/animals
https://api.example.com/v1/employees
不能這么寫:
-獲取所有圖書:https://127.0.0.1/api/get_all_books
-新增一本書:https://127.0.0.1/api/add_book
同一都用這個:
https://api.example.com/v1/books
5、method
GET :從服務(wù)器取出資源(一項或多項)
POST :在服務(wù)器新建一個資源
PUT :在服務(wù)器更新資源(客戶端提供改變后的完整資源)
PATCH :在服務(wù)器更新資源(客戶端提供改變的屬性)
DELETE :從服務(wù)器刪除資源
6、過濾,通過在url上傳參的形式傳遞搜索條件
https://api.example.com/v1/zoos?limit=10:指定返回記錄的數(shù)量
https://api.example.com/v1/zoos?offset=10:指定返回記錄的開始位置
https://api.example.com/v1/zoos?page=2&per_page=100:指定第幾頁,以及每頁的記錄數(shù)
https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回結(jié)果按照哪個屬性排序,以及排序順序
https://api.example.com/v1/zoos?animal_type_id=1:指定篩選條件
7、狀態(tài)碼
請求回去,需要有狀態(tài)碼
自定義狀態(tài)碼
status: 100表示成功
101表示用戶名密碼錯誤
102我也不知道什么錯誤
8、錯誤處理,應(yīng)返回錯誤信息,error當(dāng)做key。
-{status:100,error:'錯誤信息寫上'}
9、返回結(jié)果,針對不同操作,服務(wù)器向用戶返回的結(jié)果應(yīng)該符合以下規(guī)范。
GET /books:返回資源對象的列表(數(shù)組)
GET /books/1:返回單個資源對象
POST /books:返回新生成的資源對象 -新增,傳數(shù)據(jù),一旦新增完成,把新的資源對象返回
PUT /books/1:返回完整的資源對象
PATCH /books/1:返回完整的資源對象
DELETE /books/1:返回一個空文檔
10、Hypermedia API,RESTful API最好做到Hypermedia,即返回結(jié)果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應(yīng)該做什么。
{
status:100
msg:成功
url:127.0.0.1/books/1
}
核心:返回結(jié)果中提供鏈接
1、django寫resful規(guī)范的接口與postman軟件:模擬發(fā)請求的軟件
-格式化json格式數(shù)據(jù)
-https://www.json.cn/
put請求,django不會幫我解析body內(nèi)的數(shù)據(jù),需要自己處理
models.py
class Book(models.Model): name=models.CharField(max_length=32) price=models.CharField(max_length=32)
數(shù)據(jù)庫遷移
python3 manage.py makemigrations
python3 manage.py migrate
urls.py
url(r'^books/$', views.Books.as_view()), url(r'^books/(?P<pk>\d+)', views.Books.as_view()),
views.py
from django.http import JsonResponse from django.views import View from app01 import models class Books(View): def get(self, request): response = {'status': 100, 'data': None} books = models.Book.objects.all() lst = [{'name': book.name, 'price': book.price} for book in books] response['data'] = lst return JsonResponse(response, safe=False) def put(self, request, pk): import json data = json.loads(str(request.body, encoding='utf-8')) name = data.get('name') price = data.get('price') ret = models.Book.objects.filter(pk=pk).update(name=name, price=price) return JsonResponse({'status': 100, 'msg': '修改成功'}
login.html
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="" method="post"> <p>用戶名:<input type="text" name="name"></p> <p>密碼:<input type="password" name="pwd"></p> <p><input type="submit" value="提交"><span>{{ error }}</span></p> </form> </body> </html>
通過postman的get請求查看數(shù)據(jù)
通過postman的put請求修改數(shù)據(jù)庫中的數(shù)據(jù)
例如:
查看數(shù)據(jù)庫對應(yīng)已修改人的數(shù)據(jù)
2、drf(django rest framework)框架(django的app)
安裝:djangorestframework
-它是一個app,要在咱的項目中用,需要配置以下配置
在settings.py文件中的 INSTALLED_APPS字段中添加:
'rest_framework',
-只是快速的構(gòu)建resful規(guī)范的接口
-csrf_exempt:局部禁用csrf(csrf是可以局部使用,局部禁用)
-以后再執(zhí)行的dispatch方法是APIView的dispatch方法
-getattr和setattr
urls.py
url(r'^books/$', views.Books.as_view()), url(r'^books/(?P<pk>\d+)', views.Books.as_view()),
views.py
from rest_framework.views import APIView class Books(APIView): # 現(xiàn)在這個request對象,已經(jīng)不是原來django中的request對象了,它是rest_framework.request下的Request def put(self,request,pk): # django.core.handlers.wsgi.WSGIRequest----原來的djagno中的request的類 # 現(xiàn)在的request已經(jīng)成了:rest_framework.request.Request # print(request.PUT) # 以后再取數(shù)據(jù),直接從request.data中取 print(request.data) # 前端傳過來的編碼格式:json格式:{'name': '二狗子', 'price': '9879797987'} # 前端傳過來的編碼格式: urlencoded格式:<QueryDict: {'name': ['紅樓夢'], 'price': ['20']}> # request.data不同編碼格式過來,它可能是不同類的對象,但是用法是一樣的 # 原來的request是:request._request print(type(request._request)) print(request._request.GET) # 也能取出來(method,GET,POST,BODY) print(request.GET) return JsonResponse({'status':100,'msg':'修改成功'})
models.py(與之前上面的內(nèi)容一樣)
使用postman 測試發(fā)送數(shù)據(jù)
-重點掌握這三點:
-request.data 是個方法,包裝成了屬性,前臺傳過來body體中數(shù)據(jù)的數(shù)據(jù),放在里面
-request.query_params 這個是原來GET中的數(shù)據(jù)
-request把原來的request包裝進去了
3、序列化
-1 自己寫for循環(huán)來處理(麻煩)
-2 django提供的序列化組件(不可控)
from django.core import serializers
ret=serializers.serialize('json','queryset對象')
ret就是序列化之后的字符串了,不需要再序列化了
使用django自帶的序列化組件。
urls.py與models.py之前都一樣,主要是views.py
from rest_framework.views import APIView from django.core import serializers # django 序列化組件 class Books(APIView): def get(self,request): response={'status':100,'date':None} book=models.Book.objects.all() # 先構(gòu)造出所有書籍的字典的列表 # 用django提供的序列化組件 ret=serializers.serialize('json',book) print(type(ret),ret) #是我序列化完的值 # 返回數(shù)據(jù)是json格式數(shù)據(jù) response['date']=ret return HttpResponse(ret)
使用postman查看結(jié)果,點擊下面json按鈕,從二進制轉(zhuǎn)換成了json格式。
-3 drf給咱提供的序列化組件
-1 先導(dǎo)入
from rest_framework.serializers import Serializer
from rest_framework import serializers
-2 寫一個類,繼承Serializer
-3 在類內(nèi)部寫屬性:
name=serializers.CharField()
-4 使用:
-先生成對象,需要傳參數(shù) instance:要序列化的對象(可能是queryset,也可能是單個對象)
many:如果是queryset---True,,如果是單個對象--False
-5 對象.data --->是一個字典
urls.py與models.py與上面依然一樣不變
views.py
from rest_framework.serializers import Serializer from rest_framework import serializers class Book_Serializer(Serializer): name=serializers.CharField() # 如果只需要看一個對像,那就只寫一個就好 price=serializers.CharField() # 如果 models.py 里面的是其他類型,不是str類型,那么這里也是可以接收的,只是又轉(zhuǎn)為了str 類型 class Books(APIView): def get(self,request): books=models.Book.objects.all() # 第三步,實例化產(chǎn)生對象 # instance = books要序列化的queryset對象, many = True, 表示序列化多條 ser=Book_Serializer(instance=books,many=True) # 可以不按關(guān)鍵字傳,不寫的話,便是按位置傳參 # ser=Book_Serializer(books,many=True) # ser.data 拿到的是序列化之后的字典,字典里可能套了列表,所以safe=False return JsonResponse(ser.data,safe=False)
使用postman 來查結(jié)果
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。