參考博客
[置頂]Python系列教程 | Justin-劉清政的博客
app01/ser.py代碼
from django.db import models
# Create your models here.
class Book(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=32)
price=models.DecimalField(max_digits=5,decimal_places=2)
author=models.CharField(max_length=32)
publish=models.CharField(max_length=32)
# from rest_framework.serializers import Serializer # 就是一個(gè)類
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
# 需要繼承 Serializer
from app01.models import Book
def check_author(data):
if data.startswith('sb'):
raise ValidationError('作者名字不能以sb開頭')
else:
return data
class BookSerializer(serializers.Serializer):
id=serializers.CharField(read_only=True)
name=serializers.CharField(max_length=16,min_length=4)
# price=serializers.DecimalField()
price=serializers.CharField(write_only=True,required=True)
author=serializers.CharField(validators=[check_author]) # validators=[] 列表中寫函數(shù)內(nèi)存地址
publish=serializers.CharField()
def validate_price(self, data): # validate_字段名 接收一個(gè)參數(shù)
#如果價(jià)格小于10,就校驗(yàn)不通過
# print(type(data))
# print(data)
if float(data)>10:
return data
else:
#校驗(yàn)失敗,拋異常
raise ValidationError('價(jià)格太低')
def validate(self, validate_data): # 全局鉤子
print(validate_data)
author=validate_data.get('author')
publish=validate_data.get('publish')
if author == publish:
raise ValidationError('作者名字跟出版社一樣')
else:
return validate_data
def update(self, instance, validated_data):
#instance是book這個(gè)對象
#validated_data是校驗(yàn)后的數(shù)據(jù)
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.author=validated_data.get('author')
instance.publish=validated_data.get('publish')
instance.save() #book.save() django 的orm提供的
return instance
def create(self, validated_data):
instance=Book.objects.create(**validated_data)
return instance
# Book.objects.create(name=validated_data.get('name'))
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=Book # 對應(yīng)上models.py中的模型
fields='__all__'
# fields=('name','price','id','author') # 只序列化指定的字段
# exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
# read_only_fields=('price',)
# write_only_fields=('id',) #棄用了,使用extra_kwargs
extra_kwargs = { # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
'price': {'write_only': True},
}
app01/views.py
from django.shortcuts import render
# Create your views here.
from django.http import JsonResponse
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookSerializer
from app01.ser import BookModelSerializer
from rest_framework.response import Response #drf 提供的響應(yīng)對象
# 導(dǎo)入自己寫的response類
from app01.utils import MyResponse
class BookView(APIView):
def get(self,request,pk):
book=Book.objects.filter(id=pk).first()
#用一個(gè)類,毫無疑問,一定要實(shí)例化
#要序列化誰,就把誰傳過來
book_ser=BookSerializer(book) # 調(diào)用類的__init__
# book_ser.data 序列化對象.data就是序列化后的字典
return Response(book_ser.data)
# return JsonResponse(book_ser.data)
def put(self,request,pk):
response_msg={'status':100,'msg':'成功'}
# 找到這個(gè)對象
book = Book.objects.filter(id=pk).first()
# 得到一個(gè)序列化類的對象
# boo_ser=BookSerializer(book,request.data)
boo_ser=BookSerializer(instance=book,data=request.data)
# 要數(shù)據(jù)驗(yàn)證(回想form表單的驗(yàn)證)
if boo_ser.is_valid(): # 返回True表示驗(yàn)證通過
boo_ser.save() # 報(bào)錯(cuò)
response_msg['data']=boo_ser.data
else:
response_msg['status']=101
response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
response_msg['data']=boo_ser.errors
return Response(response_msg)
def delete(self,request,pk):
response=MyResponse()
ret=Book.objects.filter(pk=pk).delete()
return Response(response.get_dict)
class BooksView(APIView):
# def get(self,request):
# response_msg = {'status': 100, 'msg': '成功'}
# books=Book.objects.all()
# book_ser=BookSerializer(books,many=True) #序列化多條,如果序列化一條,不需要寫
# response_msg['data']=book_ser.data
# return Response(response_msg)
def get(self,request):
response=MyResponse()
books=Book.objects.all()
book_ser=BookSerializer(books,many=True) #序列化多條,如果序列化一條,不需要寫
response.data=book_ser.data
return Response(response.get_dict)
# 新增
def post(self,request):
response_msg = {'status': 100, 'msg': '成功'}
#修改才有instance,新增沒有instance,只有data
book_ser = BookSerializer(data=request.data)
# book_ser = BookSerializer(request.data) # 這個(gè)按位置傳request.data會(huì)給instance,就報(bào)錯(cuò)了
# 校驗(yàn)字段
if book_ser.is_valid():
book_ser.save()
response_msg['data']=book_ser.data
else:
response_msg['status']=102
response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
response_msg['data']=book_ser.errors
return Response(response_msg)
class BooksView2(APIView):
def get(self,request):
response=MyResponse()
books=Book.objects.all()
book=Book.objects.all().first()
book_ser=BookModelSerializer(books,many=True)
book_one_ser=BookModelSerializer(book)
print(type(book_ser))
print(type(book_one_ser))
response.data=book_ser.data
return Response(response.get_dict)
APIView源碼分析


drf的Request類


drf序列化
序列化與反序列化介紹




需要在installed_app中注冊一下'rest_framework',不然報(bào)錯(cuò),如果使用Jsonresponse返回,則可以不用注冊
序列化對象.data直接拿到j(luò)son數(shù)據(jù)
可以將rest_framework的response替換成jsonresponse,前者只是給返回的數(shù)據(jù)做了一個(gè)界面美化。
序列化字段的類型
使用charfield就返回字符串格式的json

-
數(shù)據(jù)庫定義的字段類型和序列化類寫的字段可以不一樣,都用charfield沒問題
-
路由
- 序列化器
-
需要查看哪些字段就寫哪些字段
-
字段選擇
-
將從數(shù)據(jù)庫取出的數(shù)據(jù)傳給序列化器,再使用response轉(zhuǎn)成json返回(使用drf帶的response需要先把rf注冊到app,否則報(bào)錯(cuò)模板不存在)
序列化字段選項(xiàng)
-
使用接口,put,post數(shù)據(jù)時(shí)做數(shù)據(jù)校驗(yàn)
- put方法修改數(shù)據(jù)
-
之前的修改數(shù)據(jù)方式
-
接口規(guī)范控制:抽象類abc、拋異常
-
重寫update,更新數(shù)據(jù)
-
集成的父類中有這個(gè)父類內(nèi)部調(diào)用這個(gè)方法,優(yōu)先使用重寫的這個(gè)方法
序列化組件修改數(shù)據(jù)

自定義校驗(yàn):局部鉤子、全局鉤子校驗(yàn):指定字段校驗(yàn)(類似form)
數(shù)據(jù)保存之前,可以使用鉤子校驗(yàn)規(guī)則
validate_字段名 #局部鉤子
validate # 全局鉤子

字段訪問控制
- readonly只可以查看,不可以寫的字段
- writeonly只可以寫,不可以查
class BookSerializer(serializers.Serializer):
id=serializers.CharField(read_only=True)
name=serializers.CharField(max_length=16,min_length=4)
# price=serializers.DecimalField()
price=serializers.CharField(write_only=True,required=True)
author=serializers.CharField(validators=[check_author]) # validators=[] 列表中寫函數(shù)內(nèi)存地址
publish=serializers.CharField()
- get
- 序列化多條加many
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
class BooksView(APIView):
def get(self,request):
response=MyResponse()
books=Book.objects.all()
book_ser=BookSerializer(books,many=True) #序列化多條,如果序列化一條,不需要寫
response.data=book_ser.data
return Response(response.get_dict)
- 新增post
- 需要修改序列化類的create方法
ser.py
# from rest_framework.serializers import Serializer # 就是一個(gè)類
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
# 需要繼承 Serializer
from app01.models import Book
class BookSerializer(serializers.Serializer):
id=serializers.CharField(read_only=True)
name=serializers.CharField(max_length=16,min_length=4)
# price=serializers.DecimalField()
price=serializers.CharField(write_only=True,required=True)
author=serializers.CharField(validators=[check_author]) # validators=[] 列表中寫函數(shù)內(nèi)存地址
publish=serializers.CharField()
def validate_price(self, data): # validate_字段名 接收一個(gè)參數(shù)
#如果價(jià)格小于10,就校驗(yàn)不通過
#如果價(jià)格小于10,就校驗(yàn)不通過
# print(type(data))
# print(data)
if float(data)>10:
return data
else:
#校驗(yàn)失敗,拋異常
raise ValidationError('價(jià)格太低')
def validate(self, validate_data): # 全局鉤子
print(validate_data)
author=validate_data.get('author')
publish=validate_data.get('publish')
if author == publish:
raise ValidationError('作者名字跟出版社一樣')
else:
return validate_data
def update(self, instance, validated_data):
#instance是book這個(gè)對象
#validated_data是校驗(yàn)后的數(shù)據(jù)
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.author=validated_data.get('author')
instance.publish=validated_data.get('publish')
instance.save() #book.save() django 的orm提供的
return instance
def create(self, validated_data):
instance=Book.objects.create(**validated_data)
return instance
# Book.objects.create(name=validated_data.get('name'))
views.py
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
# 新增
def post(self,request):
response_msg = {'status': 100, 'msg': '成功'}
#修改才有instance,新增沒有instance,只有data
book_ser = BookSerializer(data=request.data)
# book_ser = BookSerializer(request.data) # 這個(gè)按位置傳request.data會(huì)給instance,就報(bào)錯(cuò)了
# 校驗(yàn)字段
if book_ser.is_valid():
book_ser.save()
response_msg['data']=book_ser.data
else:
response_msg['status']=102
response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
response_msg['data']=book_ser.errors
return Response(response_msg)
- 修改put
- 需要傳book實(shí)例
- 需要重寫update方法
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
class BookView(APIView):
def put(self,request,pk):
response_msg={'status':100,'msg':'成功'}
# 找到這個(gè)對象
book = Book.objects.filter(id=pk).first()
# 得到一個(gè)序列化類的對象
# boo_ser=BookSerializer(book,request.data)
boo_ser=BookSerializer(instance=book,data=request.data)
# 要數(shù)據(jù)驗(yàn)證(回想form表單的驗(yàn)證)
if boo_ser.is_valid(): # 返回True表示驗(yàn)證通過
boo_ser.save() # 報(bào)錯(cuò)
response_msg['data']=boo_ser.data
else:
response_msg['status']=101
response_msg['msg']='數(shù)據(jù)校驗(yàn)失敗'
response_msg['data']=boo_ser.errors
return Response(response_msg)
- delete刪除
- 直接操作book對象,不需要重寫方法
from app01.models import Book
from app01.ser import BookSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
def delete(self,request,pk):
response=MyResponse()
ret=Book.objects.filter(pk=pk).delete()
return Response(response.get_dict)
- 類封裝返回信息
app1/uitls.py
class MyResponse():
def __init__(self):
self.status=100
self.msg='成功'
@property
def get_dict(self):
return self.__dict__
if __name__ == '__main__':
res=MyResponse()
res.status=101
res.msg='查詢失敗'
# res.data={'name':'lqz'}
print(res.get_dict)

-
類封裝返回信息的使用
模型類的序列化器
- app/views.py
from rest_framework.views import APIView
from app01.models import Book
from app01.ser import BookModelSerializer
from rest_framework.response import Response #drf 提供的響應(yīng)對象
# 導(dǎo)入自己寫的response類
from app01.utils import MyResponse
class BooksView2(APIView):
def get(self,request):
response=MyResponse()
books=Book.objects.all()
book=Book.objects.all().first()
book_ser=BookModelSerializer(books,many=True)
book_one_ser=BookModelSerializer(book)
print(type(book_ser))
print(type(book_one_ser))
response.data=book_ser.data
return Response(response.get_dict)
- app/ser.py
- 對應(yīng)上models.py中的模型,不需重寫update和create
from rest_framework import serializers
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=Book # 對應(yīng)上models.py中的模型
fields='__all__'
# fields=('name','price','id','author') # 只序列化指定的字段
# exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
# read_only_fields=('price',)
# write_only_fields=('id',) #棄用了,使用extra_kwargs
extra_kwargs = { # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
'price': {'write_only': True},
}
- 不需要重寫update和create了
 - bookmodelser源碼
- 序列化多條需要傳many=true
-
加了many=true參數(shù)生成的是不同的對象
注冊app

路由分發(fā)
- 先匹配總路由,再匹配多個(gè)app的路由
- include
Django--路由控制 - 劉清政 - 博客園
Serializer高級(jí)用法
source隱藏?cái)?shù)據(jù)庫字段,使用字段別名
-
盡量隱藏?cái)?shù)據(jù)庫字段,保證與序列化字段名不一樣
小結(jié)
1 Serializer類,需要序列化什么,必須寫一個(gè)類繼承,想序列化什么字段,
就在里面寫字段,source的作用(很多字段類)
2 序列化queryset(列表)對象和真正的對象,many=True的作用,instance=要序列化的對象,
3 反序列化 instance=要序列化的對象,data=request.data
4 字段驗(yàn)證,序列化類中,給字段加屬性,局部和全局鉤子函數(shù),字段屬性的validators=[check_author]
5 當(dāng)在視圖中調(diào)用 序列化對象.is_valid()
boo_ser.is_valid(raise_exception=True) 只要驗(yàn)證不通過,直接拋異常
6 修改保存---》調(diào)用序列化對象.save(),重寫Serializer類的update方法
def update(self, instance, validated_data):
#instance是book這個(gè)對象
#validated_data是校驗(yàn)后的數(shù)據(jù)
instance.name=validated_data.get('name')
instance.price=validated_data.get('price')
instance.author=validated_data.get('author')
instance.publish=validated_data.get('publish')
instance.save() #book.save() django 的orm提供的
return instance
7 序列化得到字典,序列化對象.data
8 自己定義了一個(gè)Response對象
class MyResponse():
def __init__(self):
self.status=100
self.msg='成功'
@property
def get_dict(self):
return self.__dict__
9 反序列化的新增 序列化類(data=request.data),如果只傳了data,當(dāng)調(diào)用
序列化對象.save(),會(huì)觸發(fā)序列化類的create方法執(zhí)行,
當(dāng)傳了instance和data時(shí),調(diào)用 序列化對象.save(),會(huì)觸發(fā)序列化類的update方法執(zhí)行
10 重寫create方法(可以很復(fù)雜)
def create(self, validated_data):
instance=Book.objects.create(**validated_data)
return instance
11 ModelSerializer 跟Model做了一個(gè)對應(yīng)
class BookModelSerializer(serializers.ModelSerializer):
def validate_price(self, data):
pass
publish=serializers.CharField(source='publish.name')
class Meta:
model=Book # 對應(yīng)上models.py中的模型
fields='__all__'
# fields=('name','price','id','author','publish') # 只序列化指定的字段
# exclude=('name',) #跟fields不能都寫,寫誰,就表示排除誰
# read_only_fields=('price',)
# write_only_fields=('id',) #棄用了,使用extra_kwargs
extra_kwargs = { # 類似于這種形式name=serializers.CharField(max_length=16,min_length=4)
'price': {'write_only': True,max_length:16,min_length:4},
}
12 如果在ModelSerializer中寫一個(gè)局部鉤子或者全局鉤子,如何寫?
-跟之前一模一樣
13 many=True 能夠序列化多條的原因---》__new__是在__init__之前執(zhí)行的,造出一個(gè)空對象
14 接口:統(tǒng)一子類的行為
drf-request和drf-response
- getattr方法
定義了__getattr__(),當(dāng)訪問object不存在的屬性時(shí)會(huì)調(diào)用該方法
不定義訪問不存在的屬性時(shí)會(huì)報(bào) AttributeError
eg:
class Cat(object):
def __init__(self):
self.name = "jn"
def __getattr__(self, item):
return "tm"
cat = Cat()
print(cat.name)
print(getattr(cat, 'name'))
print("*" * 20)
print(cat.age)
print(getattr(cat, 'age'))
getattr()函數(shù)
>>> getattr(a, 'bar') # 獲取屬性 bar 值
1

-
assert斷言該傳入的request對象是django傳入的request對象,如果不是則返回
請求對象.data:前端以三種編碼方式傳入的數(shù)據(jù),都可以取出來
text/html
application/json
請求對象..query_params 與Django標(biāo)準(zhǔn)的request.GET相同,只是更換了更正確的名稱而已。
drf-response
#from rest_framework.response import Response
def __init__(self, data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
#data:你要返回的數(shù)據(jù),字典
#status:返回的狀態(tài)碼,默認(rèn)是200,
-from rest_framework import status在這個(gè)路徑下,它把所有使用到的狀態(tài)碼都定義成了常量
#template_name 渲染的模板名字(自定制模板),不需要了解
#headers:響應(yīng)頭,可以往響應(yīng)頭放東西,就是一個(gè)字典
#content_type:響應(yīng)的編碼格式,application/json和text/html;
# 瀏覽器響應(yīng)成瀏覽器json格式,postman響應(yīng)成json格式,通過配置實(shí)現(xiàn)的(默認(rèn)配置)
#不管是postman還是瀏覽器,都返回json格式數(shù)據(jù)
# drf有默認(rèn)的配置文件---》先從項(xiàng)目的setting中找,找不到,采用默認(rèn)的
# drf的配置信息,先從自己類中找--》項(xiàng)目的setting中找---》默認(rèn)的找
-局部使用:對某個(gè)視圖類有效
-在視圖類中寫如下
from rest_framework.renderers import JSONRenderer
renderer_classes=[JSONRenderer,]
-全局使用:全局的視圖類,所有請求,都有效
-在setting.py中加入如下
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默認(rèn)響應(yīng)渲染類
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 瀏覽API渲染器瀏覽器訪問時(shí),會(huì)返回瀏覽器格式
)
}

-
status響應(yīng)狀態(tài)碼
視圖
-
可以找到api.html頁面修改當(dāng)前顯示
全局和局部配置響應(yīng)
-
訪問視圖的查找順序
視圖
# 兩個(gè)視圖基類
APIView
GenericAPIView
基于GenericAPIView寫5個(gè)接口
# views.py
class Book2View(GenericAPIView):
#queryset要傳queryset對象,查詢了所有的圖書
# serializer_class使用哪個(gè)序列化類來序列化這堆數(shù)據(jù)
queryset=Book.objects
# queryset=Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
book_list=self.get_queryset()
book_ser=self.get_serializer(book_list,many=True)
return Response(book_ser.data)
def post(self,request):
book_ser = self.get_serializer(data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({'status':101,'msg':'校驗(yàn)失敗'})
class Book2DetailView(GenericAPIView):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request,pk):
book = self.get_object()
book_ser = self.get_serializer(book)
return Response(book_ser.data)
def put(self, request,pk):
book = self.get_object()
book_ser = self.get_serializer(instance=book,data=request.data)
if book_ser.is_valid():
book_ser.save()
return Response(book_ser.data)
else:
return Response({'status': 101, 'msg': '校驗(yàn)失敗'})
def delete(self,request,pk):
ret=self.get_object().delete()
return Response({'status': 100, 'msg': '刪除成功'})
#url.py
# 使用GenericAPIView重寫的
path('books2/', views.Book2View.as_view()),
re_path('books2/(?P<pk>\d+)', views.Book2DetailView.as_view()),
-
GenericAPIView源碼
-GenricApiView的好處
基于GenericAPIView和5個(gè)視圖擴(kuò)展類寫的接口

from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# views.py
class Book3View(GenericAPIView,ListModelMixin,CreateModelMixin):
queryset=Book.objects
serializer_class = BookSerializer
def get(self,request):
return self.list(request)
def post(self,request):
return self.create(request)
class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
queryset = Book.objects
serializer_class = BookSerializer
def get(self, request,pk):
return self.retrieve(request,pk)
def put(self, request,pk):
return self.update(request,pk)
def delete(self,request,pk):
return self.destroy(request,pk)
# urls.py
# 使用GenericAPIView+5 個(gè)視圖擴(kuò)展類 重寫的
path('books3/', views.Book3View.as_view()),
re_path('books3/(?P<pk>\d+)', views.Book3DetailView.as_view()),
GenericApiView的9個(gè)視圖子類
- 進(jìn)一步省略代碼
-
使用繼承就可以使用
-
get
-
post
-
最終代碼
retrieve獲取一條,listApiView獲取多條
1.2.3 GenericAPIView的視圖子類
1)CreateAPIView
提供 post 方法
繼承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
繼承自:GenericAPIView、ListModelMixin
3)RetrieveAPIView
提供 get 方法
繼承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法
繼承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法
繼承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
提供 get、put、patch方法
繼承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
繼承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
使用ModelViewSet編寫5個(gè)接口
-
源碼分析
-
viewsets重寫了路由的as_view方法
-
最終代碼:路由增加一個(gè)參數(shù),來區(qū)分get一條或者多條
代碼
# views.py
from rest_framework.viewsets import ModelViewSet
class Book5View(ModelViewSet): #5個(gè)接口都有,但是路由有點(diǎn)問題
queryset = Book.objects
serializer_class = BookSerializer
# urls.py
# 使用ModelViewSet編寫5個(gè)接口
path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #當(dāng)路徑匹配,又是get請求,會(huì)執(zhí)行Book5View的list方法
re_path('books5/(?P<pk>\d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
源碼分析ViewSetMixin
Python全棧開發(fā)29期_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili

# 重寫了as_view
# 核心代碼(所以路由中只要配置了對應(yīng)關(guān)系,比如{'get':'list'}),當(dāng)get請求來,就會(huì)執(zhí)行l(wèi)ist方法
for method, action in actions.items():
#method:get
# action:list
handler = getattr(self, action)
#執(zhí)行完上一句,handler就變成了list的內(nèi)存地址
setattr(self, method, handler)
#執(zhí)行完上一句 對象.get=list
#for循環(huán)執(zhí)行完畢 對象.get:對著list 對象.post:對著create
繼承viewsetmixin視圖類
- 自定義get方法使用某個(gè)函數(shù)
# views.py
from rest_framework.viewsets import ViewSetMixin
class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前,也可以繼承g(shù)enricapiview
def get_all_book(self,request):
print("xxxx")
book_list = Book.objects.all()
book_ser = BookSerializer(book_list, many=True)
return Response(book_ser.data)
# urls.py
#繼承ViewSetMixin的視圖類,路由可以改寫成這樣
path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})),
https://tva1.sinaimg.cn/large/007S8ZIlgy1ggipvctuxcj31wc0goq89.jpg
總結(jié)
1 請求和響應(yīng)
2 請求 Request對象,drf新包裝的,Request.data,Request.query_params, 重寫了getattr, request._request
3 json模塊是否執(zhí)行反序列化bytes格式
4 考你:視圖類的方法中:self.request,就是當(dāng)次請求的request
5 Response:類,實(shí)例化傳一堆參,data=字典,status=狀態(tài)碼(有一堆常量),headers=響應(yīng)頭(字典),content_type=響應(yīng)的編碼方式
6 全局和局部配置,響應(yīng)格式
7 drf默認(rèn)配置文件,查找順序--》先從類中屬性找---》項(xiàng)目的setting找---》drf默認(rèn)的配置找
# 8 視圖家族
-APIView---》繼承自View
-GenicAPIView---》APIView,做了一些擴(kuò)展:
-queryset = None
-serializer_class = None
-get_queryset() 經(jīng)常用
-get_serializer() 經(jīng)常用
-get_serializer_class() 內(nèi)部來用,外部會(huì)重寫
-get_object() 經(jīng)常用,獲取一條數(shù)據(jù)(pk傳過來)
-源碼解析
queryset = self.filter_queryset(self.get_queryset()) #返回所有數(shù)據(jù)queryset對象
# lookup_url_kwarg就是pk,路由中有名分組分出來的pk
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
# {pk:4} 4 瀏覽器地址中要查詢的id號(hào)http://127.0.0.1:8000/books6/4/
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
# 根據(jù)pk=4去queryset中g(shù)et單個(gè)對象
obj = get_object_or_404(queryset, **filter_kwargs)
self.check_object_permissions(self.request, obj)
return obj
-5 個(gè)視圖擴(kuò)展類(繼承了object),每個(gè)里面寫了一個(gè)方法(ListModelMixin:list方法)
ListModelMixin,
CreateModelMixin,
UpdateModelMixin,
DestroyModelMixin,
RetrieveModelMixin
-GenericAPIView的視圖子類,9個(gè),繼承了GenicAPIView+一個(gè)或者兩個(gè)或者三個(gè)視圖擴(kuò)展類
CreateAPIView,
ListAPIView,
UpdateAPIView,
RetrieveAPIView,
DestroyAPIView,
ListCreateAPIView,
RetrieveUpdateDestroyAPIView,
RetrieveDestroyAPIView,
RetrieveUpdateAPIView
-視圖集:ModelViewSet,ReadOnlyModelViewSet:繼承了上面一堆(5個(gè)視圖擴(kuò)展和GenicAPIView)+自己寫了一個(gè)ViewSetMixin(as_view方法),只要繼承它的,路由得寫成{‘get’:‘自己定義的方法’}
-ViewSet=ViewSetMixin, views.APIView :ViewSetMixin要放在前面
-GenericViewSet=ViewSetMixin+GenicAPIView
-ViewSetMixin(as_view方法)
-ViewSetMixin+APIView=ViewSet
-ViewSetMixin+GenicAPIView=GenericViewSet




































