昨日回顧
1、web開(kāi)發(fā)模式
-前后端混合開(kāi)發(fā)
-前后端分離開(kāi)發(fā)
2、api接口
3、postman的使用(莫伊發(fā)送http請(qǐng)求的工具)
-對(duì)地址要求嚴(yán)格
-攜帶get數(shù)據(jù)
-攜帶post數(shù)據(jù)(格式)
-攜帶請(qǐng)求頭
4、drf:djangorestframework是一個(gè)django的一個(gè)app,更快速的在django框架上的寫(xiě)接口
-pip3 install djangorestframework
今日內(nèi)容
1、restful規(guī)范
-1)、REST與技術(shù)無(wú)關(guān),代表的是一種軟件架構(gòu)風(fēng)格,REST是Representational State Transfer:表征性狀態(tài)轉(zhuǎn)移
REST從資源的角度類(lèi)審視整個(gè)網(wǎng)絡(luò),它將分布在網(wǎng)絡(luò)中某個(gè)節(jié)點(diǎn)的資源通過(guò)URL進(jìn)行標(biāo)識(shí),客戶端應(yīng)用通過(guò)URL來(lái)獲取資源的表征,獲得這些表征致使這些應(yīng)用轉(zhuǎn)變狀態(tài)
所有的數(shù)據(jù),不過(guò)是通過(guò)網(wǎng)絡(luò)獲取的還是操作(增刪查改)的數(shù)據(jù),都是資源,將一切數(shù)據(jù)視為資源,是REST區(qū)別于其他架構(gòu)風(fēng)格的最本質(zhì)的屬性
對(duì)于REST這種面向資源的架構(gòu)風(fēng)格,有人提出一種全新的結(jié)構(gòu)理念,即:面向資源架構(gòu)
-2)、web API接口的設(shè)計(jì)風(fēng)格,尤其適用于前后端分離的應(yīng)用模式中
-3)、于語(yǔ)言,平臺(tái)無(wú)關(guān),任何框架都可以寫(xiě)出符合restful規(guī)范的api接口
-4)、規(guī)范:10條
-1、數(shù)據(jù)的安全保障:url鏈接一般都采用http協(xié)議進(jìn)行傳輸
-2、接口特征表現(xiàn):api關(guān)鍵字標(biāo)識(shí)
-API與用戶的通信協(xié)議,總是使用https協(xié)議 ,也即是加密傳輸 詳情:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
-https://api.baidu.com/books/
-https://www.baidu.com/api/books/
-3、多版本共存:url鏈接中標(biāo)識(shí)接口版本
-https://api.baidu.com/v1/books/
-https://api.baidu.com/v2/books/
-4、數(shù)據(jù)即是資源,軍使用名詞(可復(fù)數(shù))
-接口一般都是完成前臺(tái)數(shù)據(jù)的交互,交互的數(shù)據(jù)我們稱(chēng)之為資源
-一般提倡用醫(yī)院的附屬形式,不要用動(dòng)詞
-查詢(xún)所有圖書(shū)
-https://api.baidu.com/books/
-https://api.baidu.com/get_all_books/ #錯(cuò)誤示范
-https://api.baidu.com/delete_user/ #錯(cuò)誤示范
-https://api.baidu.com/user/ #刪除用戶的示例,疑問(wèn)一下,這到底是刪還是查?可以通過(guò)請(qǐng)求方式來(lái)區(qū)分
-5、資源操作由請(qǐng)求方式?jīng)Q定:
-https://api.baidu.com/books/ # get請(qǐng)求:獲取所有書(shū)
-https://api.baidu.com/books/1 # get請(qǐng)求:獲取主鍵為1的書(shū)
-https://api.baidu.com/books/ # post請(qǐng)求:新增一本書(shū)
-https://api.baidu.com/books/1 # put請(qǐng)求:整體修改主鍵為1的書(shū)
-https://api.baidu.com/books/1 # patch請(qǐng)求:局部修改主鍵為1的書(shū)
-https://api.baidu.com/books/1 # delete請(qǐng)求:刪除主鍵為1的書(shū)
-6、過(guò)濾。通過(guò)url上傳參的形式傳遞搜索條件
-https://api.example.com/v1/zoos?limit=10 # 指定返回記錄的數(shù)量
-https://api.example.com/v1/zoos?offset=10&limit=3 # 指定記錄開(kāi)始的位置
-https://api.example.com/v1/zoos?page=2&per_page=100 # 指定第幾頁(yè),以及每頁(yè)的記錄數(shù)
-https://api.example.com/v1/zoos?sortby=name&order=asc # 指定返回結(jié)果按照哪個(gè)屬性排序,以及排序的順序
-https://api.example.com/v1/zoos?animal_type_id=1 # 指定篩選條件
-7、響應(yīng)狀態(tài)碼
-返回?cái)?shù)據(jù)中帶狀態(tài)碼
-{'code':100}
-8、返回結(jié)果中帶錯(cuò)誤信息
-{'code':100,'msg':'失敗的原因'}
-9、服務(wù)器向用戶的返回結(jié)果,該符合一下規(guī)范
GET/collection:返回資源對(duì)象的列表(數(shù)組)
GET/collection/resource:返回單個(gè)資源對(duì)象(字典)
POST/collection:返回新生成的資源對(duì)象(新增后的對(duì)象字典)
PUT/collection/resource:返回完整的資源對(duì)象(修改后的對(duì)象字典)
PATCH/collection/resource:返回完整的資源對(duì)象(修改后的對(duì)象字典)
DELETE/collection/resource:返回一個(gè)空文檔
-10、返回的數(shù)據(jù)中帶鏈接地址,連向其他API方法,使得用戶不查文檔,也知道下一步應(yīng)該做什么。
-查詢(xún)id為1的圖書(shū)接口,返回結(jié)果示例
{'code':100,
'msg':'成功',
'result':
{'title':'金瓶梅',
'price':12.3,
'publish':'https://127.0.0.1/api/v1/publish/3'
}
}
2、APIview源碼分析
-1 APIview的as_view
-內(nèi)部還是執(zhí)行了View的閉包函數(shù)view
-禁用掉了csrf
-一切皆對(duì)象,函數(shù)也是對(duì)象 函數(shù)地址.name=lqz
-2 原生View類(lèi)中過(guò)的as_view中的閉包函數(shù)view
-本質(zhì)執(zhí)行了self.dispatch(request, *args, **kwargs),執(zhí)行的是APIView的dispatch
-3 APIView的dispatch
def dispatch(self, request, *args, **kwargs):
# DRF的Request類(lèi)的對(duì)象,內(nèi)部有request._request,是原生request
request = self.initialize_request(request, *args, **kwargs)
self.request = request
try:
self.initial(request, *args, **kwargs)
'''
#認(rèn)證,權(quán)限,頻率
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
'''
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
response = handler(request, *args, **kwargs)
except Exception as exc:
# 全局的異常捕獲
response = self.handle_exception(exc)
# 把視圖函數(shù)(類(lèi))返回的response,又包裝了一下
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
3、Request類(lèi)分析
rest framework 傳入視圖的request對(duì)象不再是django默認(rèn)的HttpRequest對(duì)象,而是REST framework提供的擴(kuò)展了HttpRequest類(lèi)的Request類(lèi)的對(duì)象。
REST framework 提供了Parser解析器,在接收到請(qǐng)求后會(huì)自動(dòng)根據(jù)content-type指明的請(qǐng)求數(shù)據(jù)類(lèi)型(JSON,表單等)將請(qǐng)求數(shù)據(jù)進(jìn)行parser解析,解析為類(lèi)字典【QueryDict】
對(duì)象保存到Request對(duì)象中。
Request對(duì)象的數(shù)據(jù)是自動(dòng)根據(jù)前端發(fā)送的數(shù)據(jù)的格式進(jìn)行解析之后的結(jié)果。
無(wú)論前端發(fā)送哪中格式的數(shù)據(jù),我們都可以以統(tǒng)一的方式讀取數(shù)據(jù)。
-1)、Request類(lèi)
-request._request : 原生request
-request.data : 返回解析之后的請(qǐng)求體數(shù)據(jù), post請(qǐng)求提交的數(shù)據(jù)(urlencoded,json,formdata)request.POST里只能取urlencoded和formdata兩種格式的數(shù)據(jù)
-request.query_params : 原生的request.GET,為了遵循restful規(guī)范,換殼更準(zhǔn)正確的名字而已。
-request.FILES:新的
-重寫(xiě)了__getattr__,新的request.原來(lái)私有·所有的屬性和方法,都能直接拿到
def __getattr__(self, attr):
return getattr(self._request, attr)
4、序列化組件介紹
-作用:
-1、序列化,序列化器會(huì)把模型對(duì)象轉(zhuǎn)換成字典,經(jīng)過(guò)response以后變成json字符串
-Book--序列化器--》字典--通過(guò)drf:Response-->json格式字符串---》傳給前端
-2、反序列化,把客戶端發(fā)送過(guò)來(lái)的數(shù)據(jù),經(jīng)過(guò)request以后變成字典,序列化器可以把字典轉(zhuǎn)成模型
-json格式數(shù)據(jù)---drf:Request==》字典--序列化器---Book
-3、反序列化,完成數(shù)據(jù)校驗(yàn)功能
5 序列化組件簡(jiǎn)單使用
1 序列化的使用
-寫(xiě)一個(gè)序列化類(lèi)繼承serializers.Serializer
-在類(lèi)中寫(xiě)要序列化的字段
-在視圖類(lèi)中,實(shí)例化得到一個(gè)序列化類(lèi)的對(duì)象,把要序列化的數(shù)據(jù)傳入
ser=BookSerializer(instance=res,many=True)
-得到字典
ser.data就是序列化后的字典
5.1、代碼實(shí)現(xiàn)
serializer.py
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
# 要序列化哪個(gè)字段
id=serializers.IntegerField()
# id=serializers.CharField()
title=serializers.CharField(max_length=32)
price=serializers.DecimalField(max_digits=5, decimal_places=2)
# publish=serializers.CharField(max_length=32)
models.py
class Book(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish = models.CharField(max_length=32)
views.py
from app01 import models
from app01.serializer import BookSerializer
class Book(APIView):
def get(self,request,*args,**kwargs):
res=models.Book.objects.all()
# 借助序列化器
# 如果是多條,就是many=True
# 如果是單個(gè)對(duì)象,就不寫(xiě)
ser=BookSerializer(instance=res,many=True)
# 通過(guò)序列化器得到的字典
# ser.data
print(ser.data)
return Response(ser.data)
urls.py
path('books/', views.Book.as_view()),
6 序列化類(lèi)字段類(lèi)型和字段參數(shù)
字段類(lèi)型(記列的這幾個(gè))
-IntegerField
-CharField
-DecimalField
-DateTimeField
-。。。跟models中大差不差
常用字段參數(shù)
-選項(xiàng)參數(shù)
max_length 最大長(zhǎng)度
min_lenght 最小長(zhǎng)度
allow_blank 是否允許為空
trim_whitespace 是否截?cái)嗫瞻鬃址? max_value 最小值
min_value 最大值
-通用參數(shù)
#重點(diǎn)
read_only 表明該字段僅用于序列化輸出,默認(rèn)False
write_only 表明該字段僅用于反序列化輸入,默認(rèn)False
# 掌握
required 表明該字段在反序列化時(shí)必須輸入,默認(rèn)True
default 反序列化時(shí)使用的默認(rèn)值
allow_null 表明該字段是否允許傳入None,默認(rèn)False
# 了解
validators 該字段使用的驗(yàn)證器
error_messages 包含錯(cuò)誤編號(hào)與錯(cuò)誤信息的字典
7 序列化器的保存功能
如果序列化類(lèi)繼承的是Serializer,必須重寫(xiě)create方法
使用方式
-視圖類(lèi)
def post(self, request):
print(request.data)
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save() # 保存到數(shù)據(jù)庫(kù)中
return Response(ser.data)
else:
# 沒(méi)有校驗(yàn)通過(guò)的錯(cuò)誤信息
return Response(ser.errors)
-序列化類(lèi)
class BookSerializer(serializers.Serializer):
...
def create(self, validated_data):
# 為什么要重寫(xiě)create?
res=models.Book.objects.create(**validated_data)
print(res)
return res
8 序列化器的字段校驗(yàn)功能
三種方式
-字段自己的校驗(yàn)規(guī)則(max_length...)
-validators的校驗(yàn)
publish = serializers.CharField(max_length=32,validators=[check,])
def check(data):
if len(data)>10:
raise ValidationError('最長(zhǎng)不能超過(guò)10')
else:
return data
-局部和全局鉤子
# 局部鉤子,validate_字段名,需要帶一個(gè)data,data就是該字段的數(shù)據(jù)
def validate_title(self, data):
if data.startswith('sb'):
raise ValidationError('不能以sb開(kāi)頭')
else:
return data
# 全局鉤子
def validate(self, attrs):
title=attrs.get('title')
publish=attrs.get('publish')
if title==publish:
raise ValidationError('書(shū)名不能跟出版社同名')
else:
return attrs
9 read_only和write_only
read_only 表明該字段僅用于序列化輸出,默認(rèn)False
write_only 表明該字段僅用于反序列化輸入,默認(rèn)False
class BookSerializer(serializers.Serializer):
# 要序列化哪個(gè)字段
id = serializers.IntegerField(required=False)
# id=serializers.CharField()
title = serializers.CharField(max_length=32,min_length=2,read_only=True)
price = serializers.DecimalField(max_digits=5, decimal_places=2)
# 序列化的時(shí)候看不到
publish = serializers.CharField(max_length=32,validators=[check,],write_only=True)