Django REST framework 框架是一個用於構建Web API 的強大而又靈活的工具。前端
一般簡稱爲DRF框架 或 REST framework。python
特色
提供了定義序列化器Serializer的方法,能夠快速根據 Django ORM 或者其它庫自動序列化/反序列化;
提供了豐富的類視圖、Mixin擴展類,簡化視圖的編寫;
豐富的定製層級:函數視圖、類視圖、視圖集合到自動生成 API,知足各類須要;
多種身份認證和權限認證方式的支持;
內置了限流系統;
直觀的 API web 界面;
可擴展性,插件豐富
環境安裝與配置
1. 安裝DRF
pip install djangorestframework
2. 添加rest_framework應用
咱們利用在Django框架學習中建立的demo工程,在settings.py的INSTALLED_APPS中添加'rest_framework'。web
INSTALLED_APPS = [
...
'rest_framework',
]
見識DRF的魅力
1. 建立序列化器
在booktest應用中新建serializers.py用於保存該應用的序列化器。數據庫
建立一個BookInfoSerializer用於序列化與反序列化。django
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = '__all__'
model 指明該序列化器處理的數據字段從模型類BookInfo參考生成
fields 指明該序列化器包含模型類中的哪些字段,'__all__'指明包含全部字段
2. 編寫視圖
在booktest應用的views.py中建立視圖BookInfoViewSet,這是一個視圖集合。json
from rest_framework.viewsets import ModelViewSet
from .serializers import BookInfoSerializer
from .models import BookInfo
class BookInfoViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
queryset 指明該視圖集在查詢數據時使用的查詢集
serializer_class 指明該視圖在進行序列化或反序列化時使用的序列化器
3. 定義路由
在booktest應用的urls.py中定義路由信息。後端
from . import views
from rest_framework.routers import DefaultRouter
urlpatterns = [
...
]
router = DefaultRouter() # 能夠處理視圖的路由器
router.register(r'books', views.BookInfoViewSet) # 向路由器中註冊視圖集
urlpatterns += router.urls # 將路由器中的因此路由信息追到到django的路由列表中
api
Serializer序列化器
1. 建立Serializer對象
定義好Serializer類後,就能夠建立Serializer對象了。瀏覽器
Serializer的構造方法爲:服務器
Serializer(instance=None, data=empty, **kwarg)
說明:
1)用於序列化時,將模型類對象傳入instance參數
2)用於反序列化時,將要被反序列化的數據傳入data參數
3)除了instance和data參數外,在構造Serializer對象時,還可經過context參數額外添加數據,如
serializer = AccountSerializer(account, context={'request': request})
經過context參數附加的數據,能夠經過Serializer對象的context屬性獲取。
2. 基本使用
1) 先查詢出一個圖書對象
from booktest.models import BookInfo
book = BookInfo.objects.get(id=2)
2) 構造序列化器對象
from booktest.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
3)獲取序列化數據
經過data屬性能夠獲取序列化後的數據
serializer.data
# {'id': 2, 'btitle': '天龍八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}
4)若是要被序列化的是包含多條數據的查詢集QuerySet,能夠經過添加many=True參數補充說明
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
# [OrderedDict([('id', 2), ('btitle', '天龍八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bco
3. 關聯對象嵌套序列化
若是須要序列化的數據中包含有其餘關聯對象,則對關聯對象數據的序列化須要指明。
1) PrimaryKeyRelatedField
此字段將被序列化爲關聯對象的主鍵。
hbook = serializers.PrimaryKeyRelatedField(label='圖書', read_only=True)
或
hbook = serializers.PrimaryKeyRelatedField(label='圖書', queryset=BookInfo.objects.all())
指明字段時須要包含read_only=True或者queryset參數:
包含read_only=True參數時,該字段將不能用做反序列化使用
包含queryset參數時,將被用做反序列化時參數校驗使用
2) StringRelatedField
此字段將被序列化爲關聯對象的字符串表示方式(即__str__方法的返回值)
hbook = serializers.StringRelatedField(label='圖書')
3)HyperlinkedRelatedField
此字段將被序列化爲獲取關聯對象數據的接口連接
hbook = serializers.HyperlinkedRelatedField(label='圖書', read_only=True, view_name='books-detail')
必須指明view_name參數,以便DRF根據視圖名稱尋找路由,進而拼接成完整URL。
4)SlugRelatedField
此字段將被序列化爲關聯對象的指定字段數據
hbook = serializers.SlugRelatedField(label='圖書', read_only=True, slug_field='bpub_date')
slug_field指明使用關聯對象的哪一個字段
5)使用關聯對象的序列化器
自定義序列化器對象
hbook = BookInfoSerializer()
6) 重寫to_representation方法
序列化器的每一個字段實際都是由該字段類型的to_representation方法決定格式的,能夠經過重寫該方法來決定格式。
注意,to_representations方法不只侷限在控制關聯對象格式上,適用於各個序列化器字段類型。
自定義一個新的關聯字段:
class BookRelateField(serializers.RelatedField):
"""自定義用於處理圖書的字段"""
def to_representation(self, value):
return 'Book: %d %s' % (value.id, value.btitle)
指明hbook爲BookRelateField類型
hbook = BookRelateField(read_only=True)
many參數
若是關聯的對象數據不是隻有一個,而是包含多個數據,如想序列化圖書BookInfo數據,每一個BookInfo對象關聯的英雄HeroInfo對象可能有多個,此時關聯字段類型的指明仍可以使用上述幾種方式,只是在聲明關聯字段時,多補充一個many=True參數便可。
此處僅拿PrimaryKeyRelatedField類型來舉例,其餘相同。
反序列化使用
1. 驗證
使用序列化器進行反序列化時,須要對數據進行驗證後,才能獲取驗證成功的數據或保存成模型類對象。
在獲取反序列化的數據前,必須調用is_valid()方法進行驗證,驗證成功返回True,不然返回False。
驗證失敗,能夠經過序列化器對象的errors屬性獲取錯誤信息,返回字典,包含了字段和字段的錯誤。若是是非字段錯誤,能夠經過修改REST framework配置中的NON_FIELD_ERRORS_KEY來控制錯誤字典中的鍵名。
驗證成功,能夠經過序列化器對象的validated_data屬性獲取數據。
在定義序列化器時,指明每一個字段的序列化類型和選項參數,自己就是一種驗證行爲。
is_valid()方法還能夠在驗證失敗時拋出異常serializers.ValidationError,能夠經過傳遞raise_exception=True參數開啓,REST framework接收到此異常,會向前端返回HTTP 400 Bad Request響應。
# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)
1)validate_<field_name>
對<field_name>字段進行驗證,如
class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
...
def validate_btitle(self, value):
if 'django' not in value.lower():
raise serializers.ValidationError("圖書不是關於Django的")
return value
2)validate
在序列化器中須要同時對多個字段進行比較驗證時,能夠定義validate方法來驗證,如
class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
...
def validate(self, attrs):
bread = attrs['bread']
bcomment = attrs['bcomment']
if bread < bcomment:
raise serializers.ValidationError('閱讀量小於評論量')
return attrs
3)validators
在字段中添加validators選項參數,也能夠補充驗證行爲,如
def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("圖書不是關於Django的")
class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名稱', max_length=20, validators=[about_django])
bpub_date = serializers.DateField(label='發佈日期', required=False)
bread = serializers.IntegerField(label='閱讀量', required=False)
bcomment = serializers.IntegerField(label='評論量', required=False)
image = serializers.ImageField(label='圖片', required=False)
4)REST framework提供的validators:
UniqueValidator
單字段惟一,如
from rest_framework.validators import UniqueValidator
slug = SlugField(
max_length=100,
validators=[UniqueValidator(queryset=BlogPost.objects.all())]
)
UniqueTogetherValidation
聯合惟一,如
from rest_framework.validators import UniqueTogetherValidator
class ExampleSerializer(serializers.Serializer):
# ...
class Meta:
validators = [
UniqueTogetherValidator(
queryset=ToDoItem.objects.all(),
fields=('list', 'position')
)
]
2. 保存
若是在驗證成功後,想要基於validated_data完成數據對象的建立,能夠經過實現create()和update()兩個方法來實現。
from db.serializers import BookInfoSerializer
data = {'btitle': '封神演義'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 封神演義>
from db.models import BookInfo
book = BookInfo.objects.get(id=2)
data = {'btitle': '倚天劍'}
serializer = BookInfoSerializer(book, data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 倚天劍>
book.btitle # '倚天劍'
若是建立序列化器對象的時候,沒有傳遞instance實例,則調用save()方法的時候,create()被調用,相反,若是傳遞了instance實例,則調用save()方法的時候,update()被調用。
1) 在對序列化器進行save()保存時,能夠額外傳遞數據,這些數據能夠在create()和update()中的validated_data參數獲取到
serializer.save(owner=request.user)
2)默認序列化器必須傳遞全部required的字段,不然會拋出驗證異常。可是咱們可使用partial參數來容許部分字段更新
# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)
模型類序列化器ModelSerializer
若是咱們想要使用序列化器對應的是Django的模型類,DRF爲咱們提供了ModelSerializer模型類序列化器來幫助咱們快速建立一個Serializer類。
ModelSerializer與常規的Serializer相同,但提供了:
基於模型類自動生成一系列字段
基於模型類自動爲Serializer生成validators,好比unique_together
包含默認的create()和update()的實現
1. 定義
好比咱們建立一個BookInfoSerializer
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = '__all__'
model 指明參照哪一個模型類
fields 指明爲模型類的哪些字段生成
2. 指定字段
1) 使用fields來明確字段,__all__表名包含全部字段,也能夠寫明具體哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date')
2) 使用exclude能夠明確排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
exclude = ('image',)
3) 默認ModelSerializer使用主鍵做爲關聯字段,可是咱們可使用depth來簡單的生成嵌套表示,depth應該是整數,代表嵌套的層級數量。如:
class HeroInfoSerializer2(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
造成的序列化器以下:
HeroInfoSerializer():
id = IntegerField(label='ID', read_only=True)
hname = CharField(label='名稱', max_length=20)
hgender = ChoiceField(choices=((0, 'male'), (1, 'female')), label='性別', required=False, validators=[<django.core.valators.MinValueValidator object>, <django.core.validators.MaxValueValidator object>])
hcomment = CharField(allow_null=True, label='描述信息', max_length=200, required=False)
hbook = NestedSerializer(read_only=True):
id = IntegerField(label='ID', read_only=True)
btitle = CharField(label='名稱', max_length=20)
bpub_date = DateField(allow_null=True, label='發佈日期', required=False)
bread = IntegerField(label='閱讀量', max_value=2147483647, min_value=-2147483648, required=False)
bcomment = IntegerField(label='評論量', max_value=2147483647, min_value=-2147483648, required=False)
image = ImageField(allow_null=True, label='圖片', max_length=100, required=False)
4) 顯示指明字段,如:
class HeroInfoSerializer(serializers.ModelSerializer):
hbook = BookInfoSerializer()
class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
5) 指明只讀字段
能夠經過read_only_fields指明只讀字段,即僅用於序列化輸出的字段
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
3. 添加額外參數
咱們可使用extra_kwargs參數爲ModelSerializer添加或修改原有的選項參數
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
extra_kwargs = {
'bread': {'min_value': 0, 'required': True},
'bcomment': {'min_value': 0, 'required': True},
}
視圖
1. Request
REST framework 傳入視圖的request對象再也不是Django默認的HttpRequest對象,而是REST framework提供的擴展了HttpRequest類的Request類的對象。
REST framework 提供了Parser解析器,在接收到請求後會自動根據Content-Type指明的請求數據類型(如JSON、表單等)將請求數據進行parse解析,解析爲類字典對象保存到Request對象中。
Request對象的數據是自動根據前端發送數據的格式進行解析以後的結果。
不管前端發送的哪一種格式的數據,咱們均可以以統一的方式讀取數據。
經常使用屬性
1).data
request.data 返回解析以後的請求體數據。相似於Django中標準的request.POST和 request.FILES屬性,但提供以下特性:
包含了解析以後的文件和非文件數據
包含了對POST、PUT、PATCH請求方式解析後的數據
利用了REST framework的parsers解析器,不只支持表單類型數據,也支持JSON數據
2).query_params
request.query_params與Django標準的request.GET相同,只是更換了更正確的名稱而已。
2. Response
rest_framework.response.Response
REST framework提供了一個響應類Response,使用該類構造響應對象時,響應的具體數據內容會被轉換(render渲染)成符合前端需求的類型。
REST framework提供了Renderer 渲染器,用來根據請求頭中的Accept(接收數據類型聲明)來自動轉換響應數據到對應格式。若是前端請求中未進行Accept聲明,則會採用默認方式處理響應數據,咱們能夠經過配置來修改默認響應格式。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默認響應渲染類
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 瀏覽API渲染器
)
}
構造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)
data數據不要是render處理以後的數據,只需傳遞python的內建類型數據便可,REST framework會使用renderer渲染器處理data。
data不能是複雜結構的數據,如Django的模型類對象,對於這樣的數據咱們可使用Serializer序列化器序列化處理後(轉爲了Python字典類型)再傳遞給data參數。
參數說明:
data: 爲響應準備的序列化處理後的數據;
status: 狀態碼,默認200;
template_name: 模板名稱,若是使用HTMLRenderer 時需指明;
headers: 用於存放響應頭信息的字典;
content_type: 響應數據的Content-Type,一般此參數無需傳遞,REST framework會根據前端所需類型數據來設置該參數。
經常使用屬性:
1).data
傳給response對象的序列化後,但還沒有render處理的數據
2).status_code
狀態碼的數字
3).content
通過render處理後的響應數據
3. 狀態碼
爲了方便設置狀態碼,REST framewrok在rest_framework.status模塊中提供了經常使用狀態碼常量。
1)信息告知 - 1xx
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2)成功 - 2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3)重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4)客戶端錯誤 - 4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5)服務器錯誤 - 5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
視圖說明
1. 兩個基類
1)APIView
rest_framework.views.APIView
APIView是REST framework提供的全部視圖的基類,繼承自Django的View父類。
APIView與View的不一樣之處在於:
傳入到視圖方法中的是REST framework的Request對象,而不是Django的HttpRequeset對象;
視圖方法能夠返回REST framework的Response對象,視圖會爲響應數據設置(render)符合前端要求的格式;
任何APIException異常都會被捕獲到,而且處理成合適的響應信息;
在進行dispatch()分發前,會對請求進行身份認證、權限檢查、流量控制。
支持定義的屬性:
authentication_classes 列表或元祖,身份認證類
permissoin_classes 列表或元祖,權限檢查類
throttle_classes 列表或元祖,流量控制類
在APIView中仍以常規的類視圖定義方法來實現get() 、post() 或者其餘請求方式的方法。
舉例:
from rest_framework.views import APIView
from rest_framework.response import Response
# url(r'^books/$', views.BookListView.as_view()),
class BookListView(APIView):
def get(self, request):
books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True)
return Response(serializer.data)
2)GenericAPIView
rest_framework.generics.GenericAPIView
繼承自APIVIew,增長了對於列表視圖和詳情視圖可能用到的通用支持方法。一般使用時,可搭配一個或多個Mixin擴展類。
支持定義的屬性:
列表視圖與詳情視圖通用:
queryset 列表視圖的查詢集
serializer_class 視圖使用的序列化器
列表視圖使用:
pagination_class 分頁控制類
filter_backends 過濾控制後端
詳情頁視圖使用:
lookup_field 查詢單一數據庫對象時使用的條件字段,默認爲'pk'
lookup_url_kwarg 查詢單一數據時URL中的參數關鍵字名稱,默認與look_field相同
提供的方法:
列表視圖與詳情視圖通用:
get_queryset(self)
返回視圖使用的查詢集,是列表視圖與詳情視圖獲取數據的基礎,默認返回queryset屬性,能夠重寫,例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
get_serializer_class(self)
返回序列化器類,默認返回serializer_class,能夠重寫,例如:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
get_serializer(self, args, *kwargs)
返回序列化器對象,被其餘視圖或擴展類使用,若是咱們在視圖中想要獲取序列化器對象,能夠直接調用此方法。
注意,在提供序列化器對象的時候,REST framework會向對象的context屬性補充三個數據:request、format、view,這三個數據對象能夠在定義序列化器時使用。
詳情視圖使用:
get_object(self) 返回詳情視圖所需的模型類數據對象,默認使用lookup_field參數來過濾queryset。 在試圖中能夠調用該方法獲取詳情信息的模型類對象。
若詳情訪問的模型類對象不存在,會返回404。
該方法會默認使用APIView提供的check_object_permissions方法檢查當前對象是否有權限被訪問。
舉例:
# url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),
class BookDetailView(GenericAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
def get(self, request, pk):
book = self.get_object()
serializer = self.get_serializer(book)
return Response(serializer.data)
2. 五個擴展類
1)ListModelMixin
列表視圖擴展類,提供list(request, *args, **kwargs)方法快速實現列表視圖,返回200狀態碼。
該Mixin的list方法會對數據進行過濾和分頁。
2)CreateModelMixin
建立視圖擴展類,提供create(request, *args, **kwargs)方法快速實現建立資源的視圖,成功返回201狀態碼。
若是序列化器對前端發送的數據驗證失敗,返回400錯誤。
3) RetrieveModelMixin
詳情視圖擴展類,提供retrieve(request, *args, **kwargs)方法,能夠快速實現返回一個存在的數據對象。
若是存在,返回200, 不然返回404。
4)UpdateModelMixin
更新視圖擴展類,提供update(request, *args, **kwargs)方法,能夠快速實現更新一個存在的數據對象。
同時也提供partial_update(request, *args, **kwargs)方法,能夠實現局部更新。
成功返回200,序列化器校驗數據失敗時,返回400錯誤。
5)DestroyModelMixin
刪除視圖擴展類,提供destroy(request, *args, **kwargs)方法,能夠快速實現刪除一個存在的數據對象。
成功返回204,不存在返回404。
3. 幾個可用子類視圖
1) CreateAPIView
提供 post 方法
繼承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
繼承自:GenericAPIView、ListModelMixin
3)RetireveAPIView
提供 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
視圖集ViewSet
使用視圖集ViewSet,能夠將一系列邏輯相關的動做放到一個類中:
list() 提供一組數據
retrieve() 提供單個數據
create() 建立數據
update() 保存數據
destory() 刪除數據
ViewSet視圖集類再也不實現get()、post()等方法,而是實現動做 action 如 list() 、create() 等。
視圖集只在使用as_view()方法的時候,纔會將action動做與具體請求方式對應上。如:
class BookInfoViewSet(viewsets.ViewSet):
def list(self, request):
...
def retrieve(self, request, pk=None):
...
在設置路由時,咱們能夠以下操做
urlpatterns = [
url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]
action屬性
在視圖集中,咱們能夠經過action對象屬性來獲取當前請求視圖集時的action動做是哪一個。
例如:
def get_serializer_class(self):
if self.action == 'create':
return OrderCommitSerializer
else:
return OrderDataSerializer
經常使用視圖集父類
1) ViewSet
繼承自APIView,做用也與APIView基本相似,提供了身份認證、權限校驗、流量管理等。
在ViewSet中,沒有提供任何動做action方法,須要咱們本身實現action方法。
2)GenericViewSet
繼承自GenericAPIView,做用也與GenericAPIVIew相似,提供了get_object、get_queryset等方法便於列表視圖與詳情信息視圖的開發。
3)ModelViewSet
繼承自GenericAPIVIew,同時包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
繼承自GenericAPIVIew,同時包括了ListModelMixin、RetrieveModelMixin。
視圖集中定義附加action動做
在視圖集中,除了上述默認的方法動做外,還能夠添加自定義動做。
添加自定義動做須要使用rest_framework.decorators.action裝飾器。
以action裝飾器裝飾的方法名會做爲action動做名,與list、retrieve等同。
action裝飾器能夠接收兩個參數:
methods: 該action支持的請求方式,列表傳遞
detail: 表示是action中要處理的是不是視圖資源的對象(便是否經過url路徑獲取主鍵)
True 表示使用經過URL獲取的主鍵對應的數據對象
False 表示不使用URL獲取主鍵
路由Routers
對於視圖集ViewSet,咱們除了能夠本身手動指明請求方式與動做action之間的對應關係外,還可使用Routers來幫助咱們快速實現路由信息。
REST framework提供了兩個router
SimpleRouter
DefaultRouter
1. 使用方法
1) 建立router對象,並註冊視圖集,例如
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'books', BookInfoViewSet, base_name='book')
register(prefix, viewset, base_name)
prefix 該視圖集的路由前綴
viewset 視圖集
base_name 路由名稱的前綴
如上述代碼會造成的路由以下:
^books/$ name: book-list
^books/{pk}/$ name: book-detail
2)添加路由數據
能夠有兩種方式:
urlpatterns = [
...
]
urlpatterns += router.urls
或
urlpatterns = [
...
url(r'^', include(router.urls))
]
2. 視圖集中包含附加action的
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
@action(methods=['get'], detail=False)
def latest(self, request):
...
@action(methods=['put'], detail=True)
def read(self, request, pk):
...
此視圖集會造成的路由:
^books/latest/$ name: book-latest
^books/{pk}/read/$ name: book-read
其餘功能
1. 認證Authentication
能夠在配置文件中配置全局默認的認證方案
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本認證
'rest_framework.authentication.SessionAuthentication', # session認證
)
}
也能夠在每一個視圖中經過設置authentication_classess屬性來設置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication)
...
認證失敗會有兩種可能的返回值:
401 Unauthorized 未認證
403 Permission Denied 權限被禁止
2. 權限Permissions
權限控制能夠限制用戶對於視圖的訪問和對於具體數據對象的訪問。
在執行視圖的dispatch()方法前,會先進行視圖訪問權限的判斷
在經過get_object()獲取具體對象時,會進行對象訪問權限的判斷
使用
能夠在配置文件中設置默認的權限管理類,如
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
若是未指明,則採用以下默認配置
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
也能夠在具體的視圖中經過permission_classes屬性來設置,如
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
...
提供的權限
AllowAny 容許全部用戶
IsAuthenticated 僅經過認證的用戶
IsAdminUser 僅管理員用戶
IsAuthenticatedOrReadOnly 認證的用戶能夠徹底操做,不然只能get讀取
舉例
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
自定義權限
如需自定義權限,需繼承rest_framework.permissions.BasePermission父類,並實現如下兩個任何一個方法或所有
.has_permission(self, request, view)
是否能夠訪問視圖, view表示當前視圖對象
.has_object_permission(self, request, view, obj)
是否能夠訪問數據對象, view表示當前視圖, obj爲數據對象
例如:
class MyPermission(BasePermission):
def has_object_permission(self, request, view, obj):
"""控制對obj對象的訪問權限,此案例決絕全部對對象的訪問"""
return False
class BookInfoViewSet(ModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
permission_classes = [IsAuthenticated, MyPermission]
限流Throttling
能夠對接口訪問的頻次進行限制,以減輕服務器壓力。
使用
能夠在配置文件中,使用DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES進行全局配置,
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
DEFAULT_THROTTLE_RATES 可使用 second, minute, hour 或day來指明週期。
也能夠在具體視圖中經過throttle_classess屬性來配置,如
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
...
可選限流類
1) AnonRateThrottle
限制全部匿名未認證用戶,使用IP區分用戶。
使用DEFAULT_THROTTLE_RATES['anon'] 來設置頻次
2)UserRateThrottle
限制認證用戶,使用User id 來區分。
使用DEFAULT_THROTTLE_RATES['user'] 來設置頻次
3)ScopedRateThrottle
限制用戶對於每一個視圖的訪問頻次,使用ip或user id。
例如:
class ContactListView(APIView):
throttle_scope = 'contacts'
...
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
過濾Filtering
對於列表數據可能須要根據字段進行過濾,咱們能夠經過添加django-fitlter擴展來加強支持。
pip insall django-filter
在配置文件中增長過濾後端的設置:
INSTALLED_APPS = [
...
'django_filters', # 須要註冊應用,
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
在視圖中添加filter_fields屬性,指定能夠過濾的字段
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_fields = ('btitle', 'bread')
# 127.0.0.1:8000/books/?btitle=西遊記
排序
對於列表數據,REST framework提供了OrderingFilter過濾器來幫助咱們快速指明數據按照指定字段進行排序。
使用方法:
在類視圖中設置filter_backends,使用rest_framework.filters.OrderingFilter過濾器,REST framework會在請求的查詢字符串參數中檢查是否包含了ordering參數,若是包含了ordering參數,則按照ordering參數指明的排序字段對數據集進行排序。
前端能夠傳遞的ordering參數的可選字段值須要在ordering_fields中指明。
示例:
class BookListView(ListAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
filter_backends = [OrderingFilter]
ordering_fields = ('id', 'bread', 'bpub_date')
# 127.0.0.1:8000/books/?ordering=-bread
分頁Pagination
REST framework提供了分頁的支持。
咱們能夠在配置文件中設置全局的分頁方式,如:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每頁數目
}
也可經過自定義Pagination類,來爲視圖添加不一樣分頁行爲。在視圖中經過pagination_clas屬性來指明。
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = LargeResultsSetPagination
注意:若是在視圖內關閉分頁功能,只需在視圖內設置
pagination_class = None
可選分頁器
1) PageNumberPagination
前端訪問網址形式:
GET http://api.example.org/books/?page=4
能夠在子類中定義的屬性:
page_size 每頁數目
page_query_param 前端發送的頁數關鍵字名,默認爲"page"
page_size_query_param 前端發送的每頁數目關鍵字名,默認爲None
max_page_size 前端最多能設置的每頁數量
from rest_framework.pagination import PageNumberPagination
class StandardPageNumberPagination(PageNumberPagination):
page_size_query_param = 'page_size'
max_page_size = 10
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = StandardPageNumberPagination
# 127.0.0.1/books/?page=1&page_size=2
2)LimitOffsetPagination
前端訪問網址形式:
GET http://api.example.org/books/?limit=100&offset=400
能夠在子類中定義的屬性:
default_limit 默認限制,默認值與PAGE_SIZE設置一直
limit_query_param limit參數名,默認'limit'
offset_query_param offset參數名,默認'offset'
max_limit 最大limit限制,默認None
from rest_framework.pagination import LimitOffsetPagination
class BookListView(ListAPIView):
queryset = BookInfo.objects.all().order_by('id')
serializer_class = BookInfoSerializer
pagination_class = LimitOffsetPagination
# 127.0.0.1:8000/books/?offset=3&limit=2
版本Versioning
REST framework提供了版本號的支持。
在須要獲取請求的版本號時,能夠經過request.version來獲取。
默認版本功能未開啓,request.version 返回None。
開啓版本支持功能,須要在配置文件中設置DEFAULT_VERSIONING_CLASS
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning'
}
其餘可選配置:
DEFAULT_VERSION 默認版本號,默認值爲None
ALLOWED_VERSIONS 容許請求的版本號,默認值爲None
VERSION_PARAM 識別版本號參數的名稱,默認值爲'version'
支持的版本處理方式
1) AcceptHeaderVersioning
請求頭中傳遞的Accept攜帶version
GET /bookings/ HTTP/1.1
Host: example.com
Accept: application/json; version=1.0
2)URLPathVersioning
URL路徑中攜帶
urlpatterns = [
url(
r'^(?P<version>(v1|v2))/bookings/$',
bookings_list,
name='bookings-list'
),
url(
r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
bookings_detail,
name='bookings-detail'
)
]
3)NamespaceVersioning
命名空間中定義
# bookings/urls.py
urlpatterns = [
url(r'^$', bookings_list, name='bookings-list'),
url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
]
# urls.py
urlpatterns = [
url(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
url(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
]
4)HostNameVersioning
主機域名攜帶
GET /bookings/ HTTP/1.1
Host: v1.example.com
Accept: application/json
5)QueryParameterVersioning
查詢字符串攜帶
GET /something/?version=0.1 HTTP/1.1
Host: example.com
Accept: application/json
異常處理 Exceptions
REST framework提供了異常處理,咱們能夠自定義異常處理函數。
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# 先調用REST framework默認的異常處理方法得到標準錯誤響應對象
response = exception_handler(exc, context)
# 在此處補充自定義的異常處理
if response is not None:
response.data['status_code'] = response.status_code
return response
在配置文件中聲明自定義的異常處理
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
若是未聲明,會採用默認的方式,以下
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}
REST framework定義的異常
APIException 全部異常的父類
ParseError 解析錯誤
AuthenticationFailed 認證失敗
NotAuthenticated 還沒有認證
PermissionDenied 權限決絕
NotFound 未找到
MethodNotAllowed 請求方式不支持
NotAcceptable 要獲取的數據格式不支持
Throttled 超過限流次數
ValidationError 校驗失敗
自動生成接口文檔
REST framework能夠自動幫助咱們生成接口文檔。
接口文檔以網頁的方式呈現。
自動接口文檔能生成的是繼承自APIView及其子類的視圖。
1. 安裝依賴
REST framewrok生成接口文檔須要coreapi庫的支持。
pip install coreapi
2. 設置接口文檔訪問路徑
在總路由中添加接口文檔路徑。
文檔路由對應的視圖配置爲rest_framework.documentation.include_docs_urls,
參數title爲接口文檔網站的標題。
from rest_framework.documentation import include_docs_urls
urlpatterns = [
...
url(r'^docs/', include_docs_urls(title='My API title'))
]
3. 文檔描述說明的定義位置
1) 單一方法的視圖,可直接使用類視圖的文檔字符串,如
class BookListView(generics.ListAPIView):
"""
返回全部圖書信息.
"""
2)包含多個方法的視圖,在類視圖的文檔字符串中,分開方法定義,如
class BookListCreateView(generics.ListCreateAPIView):
"""
get:
返回全部圖書信息.
post:
新建圖書.
"""
3)對於視圖集ViewSet,仍在類視圖的文檔字符串中封開定義,可是應使用action名稱區分,如
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet): """ list: 返回圖書列表數據 retrieve: 返回圖書詳情數據 latest: 返回最新的圖書數據 read: 修改圖書的閱讀量 """4. 訪問接口文檔網頁瀏覽器訪問 127.0.0.1:8000/docs/,便可看到自動生成的接口文檔。--------------------- 做者:郭大帥 來源:CSDN 原文:https://blog.csdn.net/weixin_42225318/article/details/81433662 版權聲明:本文爲博主原創文章,轉載請附上博文連接!