日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Django Rest Framework(一)

發布時間:2023/11/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Django Rest Framework(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、什么是RESTful

REST與技術無關,代表一種軟件架構風格,REST是Representational State Transfer的簡稱,中文翻譯為“表征狀態轉移”。

REST從資源的角度審視整個網絡,它將分布在網絡中某個節點的資源通過URL進行標識,客戶端應用通過URL來獲取資源的表征,獲取這些表征致使這些應用轉變狀態。

所有的數據,不管是通過網絡獲取的還是操作(增刪改查)的數據都是資源,將一切數據視為資源是REST區別于其他架構風格的最本質屬性。

對于REST這種面向資源的架構風格,有人提出一種全新的結構理念,即面向資源架構(ROA:Resource Oriented Architecture)。

?

二、RESTful API設計

1.API與用戶的通信協議,總是使用HTTPS協議。

2.域名

  • https://api.example.com ?盡量將API部署在專用域名(會存在跨域問題)
  • https://example.org ?API很簡單

3.路徑,視網絡上任何東西都是資源,均使用名詞表示(可復數)

  • https://api.example.com/v1/zoos
  • https://api.example.com/v1/animals

4.method

  • GET ?從服務器取資源(一項或多項)
  • POST ?在服務器新建一個資源
  • PUT ?在服務器更新資源(客戶端提供改變后的完整資源)
  • PATCH ?在服務器更新資源(客戶端提供改變的屬性)
  • DELETE ?從服務器刪除資源

5.過濾,通過在URL上傳參數的形式傳遞搜索條件

  • https://api.example.com/v1/zoos?limit=10:指定返回記錄的數量
  • https://api.example.com/v1/zoos?offset=10:指定返回記錄的開始位置
  • https://api.example.com/v1/zoos?page=2&per_page=100:指定第幾頁,以及每頁的記錄數
  • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序
  • https://api.example.com/v1/zoos?animal_type_id=1:指定篩選條件

6.狀態碼

200 OK - [GET]:服務器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。 202 Accepted - [*]:表示一個請求已經進入后臺排隊(異步任務) 204 NO CONTENT - [DELETE]:用戶刪除數據成功。 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作,該操作是冪等的。 401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的。 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。 500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。更多看這里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 常用狀態碼列表

7.錯誤處理,狀態碼是4XX時,應返回錯誤信息,error當作key

{error: "Invalid API key" } View Code

8.返回結果,針對不同操作,服務器向用戶返回的結果應該符合以下規范。

GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔 View Code

9.Hypermedia API,RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其它API方法,使用戶不查文檔,也知道下一步應該做什么。

{"link": {"rel": "collection https://www.example.com/zoos","href": "https://api.example.com/zoos","title": "List of zoos","type": "application/vnd.yourformat+json" }} View Code

摘自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html?

?

三、基于Django實現

路由系統:

urlpatterns = [url(r'^users', Users.as_view()), ] View Code

CBV視圖:

from django.views import View from django.http import JsonResponseclass Users(View):def get(self, request, *args, **kwargs):result = {'status': True,'data': 'response data'}return JsonResponse(result, status=200)def post(self, request, *args, **kwargs):result = {'status': True,'data': 'response data'}return JsonResponse(result, status=200) View Code

?

四、基于Django Rest framework框架實現

1.基本流程

from django.conf.urls import url, include from web.views.s1_api import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] url.py from rest_framework.views import APIView from rest_framework.response import Responseclass TestView(APIView):def dispatch(self, request, *args, **kwargs):"""請求到來之后,都要執行dispatch方法,dispatch方法根據請求方式不同觸發 get/post/put等方法注意:APIView中的dispatch方法有好多好多的功能"""return super().dispatch(request, *args, **kwargs)def get(self, request, *args, **kwargs):return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

上述是rest framework框架基本流程,重要的功能是在APIview的dispatch中觸發。

?

2.認證和授權

(1)用戶url傳入的token認證

from django.conf.urls import url, include from web.viewsimport TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptionstoken_list = ['sfsfss123kuf3j123','asijnfowerkkf9812', ]class TestAuthentication(BaseAuthentication):def authenticate(self, request):"""用戶認證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認證,默認用戶和Token和使用配置文件進行設置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER()else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()else:self.auth = None(user,token)表示驗證通過并設置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認證失敗")return ('登錄用戶', '用戶token')def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""# 驗證失敗時,返回的響應頭WWW-Authenticate對應的值passclass TestView(APIView):authentication_classes = [TestAuthentication, ]permission_classes = []def get(self, request, *args, **kwargs):print(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(2)請求頭認證

from django.conf.urls import url, include from web.viewsimport TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptionstoken_list = ['sfsfss123kuf3j123','asijnfowerkkf9812', ]class TestAuthentication(BaseAuthentication):def authenticate(self, request):"""用戶認證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認證,默認用戶和Token和使用配置文件進行設置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER()else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()else:self.auth = None(user,token)表示驗證通過并設置用戶名和Token;AuthenticationFailed異常"""import base64auth = request.META.get('HTTP_AUTHORIZATION', b'')if auth:auth = auth.encode('utf-8')auth = auth.split()if not auth or auth[0].lower() != b'basic':raise exceptions.AuthenticationFailed('驗證失敗')if len(auth) != 2:raise exceptions.AuthenticationFailed('驗證失敗')username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')if username == 'alex' and password == '123':return ('登錄用戶', '用戶token')else:raise exceptions.AuthenticationFailed('用戶名或密碼錯誤')def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""return 'Basic realm=api'class TestView(APIView):authentication_classes = [TestAuthentication, ]permission_classes = []def get(self, request, *args, **kwargs):print(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(3)多個認證規則

from django.conf.urls import url, include from web.views.s2_auth import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptionstoken_list = ['sfsfss123kuf3j123','asijnfowerkkf9812', ]class Test1Authentication(BaseAuthentication):def authenticate(self, request):"""用戶認證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認證,默認用戶和Token和使用配置文件進行設置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認值為:Noneelse:self.auth = None(user,token)表示驗證通過并設置用戶名和Token;AuthenticationFailed異常"""import base64auth = request.META.get('HTTP_AUTHORIZATION', b'')if auth:auth = auth.encode('utf-8')else:return Noneprint(auth,'xxxx')auth = auth.split()if not auth or auth[0].lower() != b'basic':raise exceptions.AuthenticationFailed('驗證失敗')if len(auth) != 2:raise exceptions.AuthenticationFailed('驗證失敗')username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')if username == 'alex' and password == '123':return ('登錄用戶', '用戶token')else:raise exceptions.AuthenticationFailed('用戶名或密碼錯誤')def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""# return 'Basic realm=api'passclass Test2Authentication(BaseAuthentication):def authenticate(self, request):"""用戶認證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認證,默認用戶和Token和使用配置文件進行設置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認值為:Noneelse:self.auth = None(user,token)表示驗證通過并設置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認證失敗")return ('登錄用戶', '用戶token')def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""passclass TestView(APIView):authentication_classes = [Test1Authentication, Test2Authentication]permission_classes = []def get(self, request, *args, **kwargs):print(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(4)認證和權限

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermissionfrom rest_framework.request import Request from rest_framework import exceptionstoken_list = ['sfsfss123kuf3j123','asijnfowerkkf9812', ]class TestAuthentication(BaseAuthentication):def authenticate(self, request):"""用戶認證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認證,默認用戶和Token和使用配置文件進行設置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認值為:Noneelse:self.auth = None(user,token)表示驗證通過并設置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認證失敗")return ('登錄用戶', '用戶token')def authenticate_header(self, request):"""Return a string to be used as the value of the `WWW-Authenticate`header in a `401 Unauthenticated` response, or `None` if theauthentication scheme should return `403 Permission Denied` responses."""passclass TestPermission(BasePermission):message = "權限驗證失敗"def has_permission(self, request, view):"""判斷是否有權限訪問當前請求Return `True` if permission is granted, `False` otherwise.:param request: :param view: :return: True有權限;False無權限"""if request.user == "管理員":return True# GenericAPIView中get_object時調用def has_object_permission(self, request, view, obj):"""視圖繼承GenericAPIView,并在其中使用get_object時獲取對象時,觸發單獨對象權限驗證Return `True` if permission is granted, `False` otherwise.:param request: :param view: :param obj: :return: True有權限;False無權限"""if request.user == "管理員":return Trueclass TestView(APIView):# 認證的動作是由request.user觸發authentication_classes = [TestAuthentication, ]# 權限# 循環執行所有的權限permission_classes = [TestPermission, ]def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(5)全局使用

上述操作中均是對單獨試圖進行特殊操作配置,如果要對全局進行配置,則需要在配置文件中寫入即可。

REST_FRAMEWORK = {'UNAUTHENTICATED_USER': None,'UNAUTHENTICATED_TOKEN': None,"DEFAULT_AUTHENTICATION_CLASSES": ["web.utils.TestAuthentication",],"DEFAULT_PERMISSION_CLASSES": ["web.utils.TestPermission",], } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Responseclass TestView(APIView):def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

?

3.用戶訪問次數/頻率限制

(1)基于用戶IP限制訪問頻率

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- import time from rest_framework.views import APIView from rest_framework.response import Responsefrom rest_framework import exceptions from rest_framework.throttling import BaseThrottle from rest_framework.settings import api_settings# 保存訪問記錄 RECORD = {'用戶IP': [12312139, 12312135, 12312133, ] }class TestThrottle(BaseThrottle):ctime = time.timedef get_ident(self, request):"""根據用戶IP和代理IP,當做請求者的唯一IPIdentify the machine making the request by parsing HTTP_X_FORWARDED_FORif present and number of proxies is > 0. If not use all ofHTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR."""xff = request.META.get('HTTP_X_FORWARDED_FOR')remote_addr = request.META.get('REMOTE_ADDR')num_proxies = api_settings.NUM_PROXIESif num_proxies is not None:if num_proxies == 0 or xff is None:return remote_addraddrs = xff.split(',')client_addr = addrs[-min(num_proxies, len(addrs))]return client_addr.strip()return ''.join(xff.split()) if xff else remote_addrdef allow_request(self, request, view):"""是否仍然在允許范圍內Return `True` if the request should be allowed, `False` otherwise.:param request: :param view: :return: True,表示可以通過;False表示已超過限制,不允許訪問"""# 獲取用戶唯一標識(如:IP)# 允許一分鐘訪問10次num_request = 10time_request = 60now = self.ctime()ident = self.get_ident(request)self.ident = identif ident not in RECORD:RECORD[ident] = [now, ]return Truehistory = RECORD[ident]while history and history[-1] <= now - time_request:history.pop()if len(history) < num_request:history.insert(0, now)return Truedef wait(self):"""多少秒后可以允許繼續訪問Optionally, return a recommended number of seconds to wait beforethe next request."""last_time = RECORD[self.ident][0]now = self.ctime()return int(60 + last_time - now)class TestView(APIView):throttle_classes = [TestThrottle, ]def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容')def throttled(self, request, wait):"""訪問次數被限制時,定制錯誤信息"""class Throttled(exceptions.Throttled):default_detail = '請求被限制.'extra_detail_singular = '請 {wait} 秒之后再重試.'extra_detail_plural = '請 {wait} 秒之后再重試.'raise Throttled(wait) views.py

(2)基于用戶IP顯示訪問頻率(利用Django緩存)

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'test_scope': '10/m',}, } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Responsefrom rest_framework import exceptions from rest_framework.throttling import SimpleRateThrottleclass TestThrottle(SimpleRateThrottle):# 配置文件定義的顯示頻率的Keyscope = "test_scope"def get_cache_key(self, request, view):"""Should return a unique cache-key which can be used for throttling.Must be overridden.May return `None` if the request should not be throttled."""if not request.user:ident = self.get_ident(request)else:ident = request.userreturn self.cache_format % {'scope': self.scope,'ident': ident}class TestView(APIView):throttle_classes = [TestThrottle, ]def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容')def throttled(self, request, wait):"""訪問次數被限制時,定制錯誤信息"""class Throttled(exceptions.Throttled):default_detail = '請求被限制.'extra_detail_singular = '請 {wait} 秒之后再重試.'extra_detail_plural = '請 {wait} 秒之后再重試.'raise Throttled(wait) views.py

(3)view中限制請求頻率

REST_FRAMEWORK = {'DEFAULT_THROTTLE_RATES': {'xxxxxx': '10/m',}, } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Responsefrom rest_framework import exceptions from rest_framework.throttling import ScopedRateThrottle# 繼承 ScopedRateThrottle class TestThrottle(ScopedRateThrottle):def get_cache_key(self, request, view):"""Should return a unique cache-key which can be used for throttling.Must be overridden.May return `None` if the request should not be throttled."""if not request.user:ident = self.get_ident(request)else:ident = request.userreturn self.cache_format % {'scope': self.scope,'ident': ident}class TestView(APIView):throttle_classes = [TestThrottle, ]# 在settings中獲取 xxxxxx 對應的頻率限制值throttle_scope = "xxxxxx"def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容')def throttled(self, request, wait):"""訪問次數被限制時,定制錯誤信息"""class Throttled(exceptions.Throttled):default_detail = '請求被限制.'extra_detail_singular = '請 {wait} 秒之后再重試.'extra_detail_plural = '請 {wait} 秒之后再重試.'raise Throttled(wait) views.py

(4)匿名時用IP限制+登錄時用Token限制

REST_FRAMEWORK = {'UNAUTHENTICATED_USER': None,'UNAUTHENTICATED_TOKEN': None,'DEFAULT_THROTTLE_RATES': {'luffy_anon': '10/m','luffy_user': '20/m',}, } settings.py from django.conf.urls import url, include from web.views.s3_throttling import TestViewurlpatterns = [url(r'^test/', TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Responsefrom rest_framework.throttling import SimpleRateThrottleclass LuffyAnonRateThrottle(SimpleRateThrottle):"""匿名用戶,根據IP進行限制"""scope = "luffy_anon"def get_cache_key(self, request, view):# 用戶已登錄,則跳過 匿名頻率限制if request.user:return Nonereturn self.cache_format % {'scope': self.scope,'ident': self.get_ident(request)}class LuffyUserRateThrottle(SimpleRateThrottle):"""登錄用戶,根據用戶token限制"""scope = "luffy_user"def get_ident(self, request):"""認證成功時:request.user是用戶對象;request.auth是token對象:param request: :return: """# return request.auth.tokenreturn "user_token"def get_cache_key(self, request, view):"""獲取緩存key:param request: :param view: :return: """# 未登錄用戶,則跳過 Token限制if not request.user:return Nonereturn self.cache_format % {'scope': self.scope,'ident': self.get_ident(request)}class TestView(APIView):throttle_classes = [LuffyUserRateThrottle, LuffyAnonRateThrottle, ]def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(5)全局使用

REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': ['api.utils.throttles.throttles.LuffyAnonRateThrottle','api.utils.throttles.throttles.LuffyUserRateThrottle',],'DEFAULT_THROTTLE_RATES': {'anon': '10/day','user': '10/day','luffy_anon': '10/m','luffy_user': '20/m',}, } settings

?

4.版本

(1)基于url的get傳參方式

如:/users?version=v1

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認版本'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version' # URL中獲取值的key } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view(),name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import QueryParameterVersioningclass TestView(APIView):versioning_class = QueryParameterVersioningdef get(self, request, *args, **kwargs):# 獲取版本print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(2)基于url的正則方式

如:/v1/users/

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認版本'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version' # URL中獲取值的key } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import URLPathVersioningclass TestView(APIView):versioning_class = URLPathVersioningdef get(self, request, *args, **kwargs):# 獲取版本print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(3)基于accept請求方式

如:Accept: application/json; version=1.0

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認版本'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version' # URL中獲取值的key } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import AcceptHeaderVersioningclass TestView(APIView):versioning_class = AcceptHeaderVersioningdef get(self, request, *args, **kwargs):# 獲取版本 HTTP_ACCEPT頭print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(4)基于主機名方法

如:v1.example.com

ALLOWED_HOSTS = ['*'] REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認版本'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version' # URL中獲取值的key } settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import HostNameVersioningclass TestView(APIView):versioning_class = HostNameVersioningdef get(self, request, *args, **kwargs):# 獲取版本print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(5)基于Django路由系統的namespace

如:example.com/v1/users/

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認版本'ALLOWED_VERSIONS': ['v1', 'v2'], # 允許的版本'VERSION_PARAM': 'version' # URL中獲取值的key } setting.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'^v1/', ([url(r'test/', TestView.as_view(), name='test'),], None, 'v1')),url(r'^v2/', ([url(r'test/', TestView.as_view(), name='test'),], None, 'v2')),] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import NamespaceVersioningclass TestView(APIView):versioning_class = NamespaceVersioningdef get(self, request, *args, **kwargs):# 獲取版本print(request.version)# 獲取版本管理的類print(request.versioning_scheme)# 反向生成URLreverse_url = request.versioning_scheme.reverse('test', request=request)print(reverse_url)return Response('GET請求,響應內容')def post(self, request, *args, **kwargs):return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(6)全局使用

REST_FRAMEWORK = {'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",'DEFAULT_VERSION': 'v1','ALLOWED_VERSIONS': ['v1', 'v2'],'VERSION_PARAM': 'version' } settings.py

?

5.解析器(parser)

根據請求頭content-type選擇對應的解析器就請求體內容處理。

(1)進處理請求頭content-type為application/json的請求體

from django.conf.urls import url, include from web.views.s5_parser import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import JSONParserclass TestView(APIView):parser_classes = [JSONParser, ]def post(self, request, *args, **kwargs):print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(2)僅處理請求頭content-type為application/x-www-form-urlencoded的請求體

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import FormParserclass TestView(APIView):parser_classes = [FormParser, ]def post(self, request, *args, **kwargs):print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(3)僅處理請求頭content-type為multipart/form-data的請求體

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import MultiPartParserclass TestView(APIView):parser_classes = [MultiPartParser, ]def post(self, request, *args, **kwargs):print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data"><input type="text" name="user" /><input type="file" name="img"><input type="submit" value="提交"></form> </body> </html> upload.html

(4)僅上傳文件

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import FileUploadParserclass TestView(APIView):parser_classes = [FileUploadParser, ]def post(self, request, filename, *args, **kwargs):print(filename)print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data"><input type="text" name="user" /><input type="file" name="img"><input type="submit" value="提交"></form> </body> </html> upload.html

(5)同時多個Parser

當同時使用多個parser時,rest framework會更具請求頭content-type自動進行比對,并使用對應parser。

from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import JSONParser, FormParser, MultiPartParserclass TestView(APIView):parser_classes = [JSONParser, FormParser, MultiPartParser, ]def post(self, request, *args, **kwargs):print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

(6)全局使用

REST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser''rest_framework.parsers.FormParser''rest_framework.parsers.MultiPartParser']} settings.py from django.conf.urls import url, include from web.views import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Responseclass TestView(APIView):def post(self, request, *args, **kwargs):print(request.content_type)# 獲取請求的值,并使用對應的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應內容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應內容') views.py

注意:個別特殊的值可以通過Django的request對象 request._request 來進行獲取

?

6.序列化

序列化用于對用戶請求數據進行驗證和數據進行序列化。

(1)自定義字段

from django.conf.urls import url, include from web.views.s6_serializers import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import modelsclass PasswordValidator(object):def __init__(self, base):self.base = basedef __call__(self, value):if value != self.base:message = 'This field must be %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 執行驗證之前調用,serializer_fields是當前字段對象passclass UserSerializer(serializers.Serializer):ut_title = serializers.CharField(source='ut.title')user = serializers.CharField(min_length=6)pwd = serializers.CharField(error_messages={'required': '密碼不能為空'}, validators=[PasswordValidator('666')])class TestView(APIView):def get(self, request, *args, **kwargs):# 序列化,將數據庫查詢字段序列化為字典data_list = models.UserInfo.objects.all()ser = UserSerializer(instance=data_list, many=True)## obj = models.UserInfo.objects.all().first()# ser = UserSerializer(instance=obj, many=False)return Response(ser.data)def post(self, request, *args, **kwargs):# 驗證,對請求發來的數據進行驗證ser = UserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應內容') views.py

(2)基于Model自動生成字段

from django.conf.urls import url, include from web.views.s6_serializers import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import modelsclass PasswordValidator(object):def __init__(self, base):self.base = str(base)def __call__(self, value):if value != self.base:message = 'This field must be %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 執行驗證之前調用,serializer_fields是當前字段對象passclass ModelUserSerializer(serializers.ModelSerializer):user = serializers.CharField(max_length=32)class Meta:model = models.UserInfofields = "__all__"# fields = ['user', 'pwd', 'ut']depth = 2extra_kwargs = {'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666), ]}}# read_only_fields = ['user']class TestView(APIView):def get(self, request, *args, **kwargs):# 序列化,將數據庫查詢字段序列化為字典data_list = models.UserInfo.objects.all()ser = ModelUserSerializer(instance=data_list, many=True)## obj = models.UserInfo.objects.all().first()# ser = UserSerializer(instance=obj, many=False)return Response(ser.data)def post(self, request, *args, **kwargs):# 驗證,對請求發來的數據進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應內容') views.py

(3)生成URL

from django.conf.urls import url, include from web.views.s6_serializers import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'),url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='detail'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import modelsclass PasswordValidator(object):def __init__(self, base):self.base = str(base)def __call__(self, value):if value != self.base:message = 'This field must be %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 執行驗證之前調用,serializer_fields是當前字段對象passclass ModelUserSerializer(serializers.ModelSerializer):ut = serializers.HyperlinkedIdentityField(view_name='detail')class Meta:model = models.UserInfofields = "__all__"extra_kwargs = {'user': {'min_length': 6},'pwd': {'validators': [PasswordValidator(666),]},}class TestView(APIView):def get(self, request, *args, **kwargs):# 序列化,將數據庫查詢字段序列化為字典data_list = models.UserInfo.objects.all()ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})## obj = models.UserInfo.objects.all().first()# ser = UserSerializer(instance=obj, many=False)return Response(ser.data)def post(self, request, *args, **kwargs):# 驗證,對請求發來的數據進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應內容') views.py

(4)自動生成URL

from django.conf.urls import url, include from web.views.s6_serializers import TestViewurlpatterns = [url(r'test/', TestView.as_view(), name='test'),url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='xxxx'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import modelsclass PasswordValidator(object):def __init__(self, base):self.base = str(base)def __call__(self, value):if value != self.base:message = 'This field must be %s.' % self.baseraise serializers.ValidationError(message)def set_context(self, serializer_field):"""This hook is called by the serializer instance,prior to the validation call being made."""# 執行驗證之前調用,serializer_fields是當前字段對象passclass ModelUserSerializer(serializers.HyperlinkedModelSerializer):ll = serializers.HyperlinkedIdentityField(view_name='xxxx')tt = serializers.CharField(required=False)class Meta:model = models.UserInfofields = "__all__"list_serializer_class = serializers.ListSerializerextra_kwargs = {'user': {'min_length': 6},'pwd': {'validators': [PasswordValidator(666), ]},'url': {'view_name': 'xxxx'},'ut': {'view_name': 'xxxx'},}class TestView(APIView):def get(self, request, *args, **kwargs):# # 序列化,將數據庫查詢字段序列化為字典data_list = models.UserInfo.objects.all()ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})# # 如果Many=True# # 或# # obj = models.UserInfo.objects.all().first()# # ser = UserSerializer(instance=obj, many=False)return Response(ser.data)def post(self, request, *args, **kwargs):# 驗證,對請求發來的數據進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應內容') views.py

?

7.分頁

(1)根據頁碼進行分頁

from django.conf.urls import url, include from rest_framework import routers from web.views import s9_paginationurlpatterns = [url(r'^test/', s9_pagination.UserViewSet.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework import serializers from .. import modelsfrom rest_framework.pagination import PageNumberPaginationclass StandardResultsSetPagination(PageNumberPagination):# 默認每頁顯示的數據條數page_size = 1# 獲取URL參數中設置的每頁顯示數據條數page_size_query_param = 'page_size'# 獲取URL參數中傳入的頁碼keypage_query_param = 'page'# 最大支持的每頁顯示的數據條數max_page_size = 1class UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(APIView):def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().order_by('-id')# 實例化分頁對象,獲取數據庫中的分頁數據paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數據response = paginator.get_paginated_response(serializer.data)return response views.py

(2)位置和個數進行分頁

from django.conf.urls import url, include from web.views import s9_paginationurlpatterns = [url(r'^test/', s9_pagination.UserViewSet.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework import serializers from .. import modelsfrom rest_framework.pagination import PageNumberPagination,LimitOffsetPaginationclass StandardResultsSetPagination(LimitOffsetPagination):# 默認每頁顯示的數據條數default_limit = 10# URL中傳入的顯示數據條數的參數limit_query_param = 'limit'# URL中傳入的數據位置的參數offset_query_param = 'offset'# 最大每頁顯得條數max_limit = Noneclass UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(APIView):def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().order_by('-id')# 實例化分頁對象,獲取數據庫中的分頁數據paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數據response = paginator.get_paginated_response(serializer.data)return response views.py

(3)游標分頁

from django.conf.urls import url, include from web.views import s9_paginationurlpatterns = [url(r'^test/', s9_pagination.UserViewSet.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework import serializers from .. import modelsfrom rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPaginationclass StandardResultsSetPagination(CursorPagination):# URL傳入的游標參數cursor_query_param = 'cursor'# 默認每頁顯示的數據條數page_size = 2# URL傳入的每頁顯示條數的參數page_size_query_param = 'page_size'# 每頁顯示數據最大條數max_page_size = 1000# 根據ID從大到小排列ordering = "id"class UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(APIView):def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().order_by('-id')# 實例化分頁對象,獲取數據庫中的分頁數據paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數據response = paginator.get_paginated_response(serializer.data)return response views.py

?

8.路由系統

(1)自定義路由

from django.conf.urls import url, include from web.views import s11_renderurlpatterns = [url(r'^test/$', s11_render.TestView.as_view()),url(r'^test\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view()),url(r'^test/(?P<pk>[^/.]+)/$', s11_render.TestView.as_view()),url(r'^test/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view()) ] urls.py from rest_framework.views import APIView from rest_framework.response import Response from .. import modelsclass TestView(APIView):def get(self, request, *args, **kwargs):print(kwargs)print(self.renderer_classes)return Response('...') views.py

(2)半自動路由

from django.conf.urls import url, include from web.views import s10_genericurlpatterns = [url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),url(r'^test/(?P<pk>\d+)/$', s10_generic.UserViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.viewsets import ModelViewSet from rest_framework import serializers from .. import modelsclass UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = UserSerializer views.py

(3)全自動路由

from django.conf.urls import url, include from rest_framework import routers from web.views import s10_genericrouter = routers.DefaultRouter() router.register(r'users', s10_generic.UserViewSet)urlpatterns = [url(r'^', include(router.urls)), ] urls.py from rest_framework.viewsets import ModelViewSet from rest_framework import serializers from .. import modelsclass UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = UserSerializer views.py

?

9.視圖

(1)GenericViewSet

from django.conf.urls import url, include from web.views.s7_viewset import TestViewurlpatterns = [url(r'test/', TestView.as_view({'get':'list'}), name='test'),url(r'detail/(?P<pk>\d+)/', TestView.as_view({'get':'list'}), name='xxxx'), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework import viewsets from rest_framework.response import Responseclass TestView(viewsets.GenericViewSet):def list(self, request, *args, **kwargs):return Response('...')def add(self, request, *args, **kwargs):passdef delete(self, request, *args, **kwargs):passdef edit(self, request, *args, **kwargs):pass views.py

(2)ModelViewSet(自定義URL)

from django.conf.urls import url, include from web.views import s10_genericurlpatterns = [url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),url(r'^test/(?P<pk>\d+)/$', s10_generic.UserViewSet.as_view({'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.viewsets import ModelViewSet from rest_framework import serializers from .. import modelsclass UserSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class UserViewSet(ModelViewSet):queryset = models.UserInfo.objects.all()serializer_class = UserSerializer views.py

(3)ModelViewSet(rest framework路由)

from django.conf.urls import url, include from rest_framework import routers from app01 import viewsrouter = routers.DefaultRouter() router.register(r'users', views.UserViewSet) router.register(r'groups', views.GroupViewSet)# Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. urlpatterns = [url(r'^', include(router.urls)), ] urls.py from rest_framework import viewsets from rest_framework import serializersclass UserSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = models.Userfields = ('url', 'username', 'email', 'groups')class GroupSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = models.Groupfields = ('url', 'name')class UserViewSet(viewsets.ModelViewSet):"""API endpoint that allows users to be viewed or edited."""queryset = User.objects.all().order_by('-date_joined')serializer_class = UserSerializerclass GroupViewSet(viewsets.ModelViewSet):"""API endpoint that allows groups to be viewed or edited."""queryset = Group.objects.all()serializer_class = GroupSerializer views.py

?

10.渲染器

根據用戶請求URL或用戶可接受的類型,篩選出合適的渲染組件

用戶請求URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json

用戶請求頭:

  • Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

(1)json

訪問URL:

  • http://127.0.0.1:8000/test/?format=json
  • http://127.0.0.1:8000/test.json
  • http://127.0.0.1:8000/test/?
from django.conf.urls import url, include from web.views import s11_renderurlpatterns = [url(r'^test/$', s11_render.TestView.as_view()),url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializersfrom rest_framework.renderers import JSONRendererfrom .. import modelsclass TestSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class TestView(APIView):renderer_classes = [JSONRenderer, ]def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all()ser = TestSerializer(instance=user_list, many=True)return Response(ser.data) views.py

(2)表格

訪問URL:

  • http://127.0.0.1:8000/test/?format=admin
  • http://127.0.0.1:8000/test.admin
  • http://127.0.0.1:8000/test/
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializersfrom rest_framework.renderers import AdminRendererfrom .. import modelsclass TestSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class TestView(APIView):renderer_classes = [AdminRenderer, ]def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all()ser = TestSerializer(instance=user_list, many=True)return Response(ser.data) views.py

(3)Form表單

訪問URL:

  • http://127.0.0.1:8000/test/?format=form
  • http://127.0.0.1:8000/test.form
  • http://127.0.0.1:8000/test/?
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializersfrom rest_framework.renderers import JSONRenderer from rest_framework.renderers import AdminRenderer from rest_framework.renderers import HTMLFormRendererfrom .. import modelsclass TestSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class TestView(APIView):renderer_classes = [HTMLFormRenderer, ]def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().first()ser = TestSerializer(instance=user_list, many=False)return Response(ser.data) views.py

(4)自定義顯示模板

訪問URL:

  • http://127.0.0.1:8000/test/?format=html
  • http://127.0.0.1:8000/test.html
  • http://127.0.0.1:8000/test/
from django.conf.urls import url, include from web.views import s11_renderurlpatterns = [url(r'^test/$', s11_render.TestView.as_view()),url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()), ] urls.py #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import TemplateHTMLRendererfrom .. import modelsclass TestSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class TestView(APIView):renderer_classes = [TemplateHTMLRenderer, ]def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().first()ser = TestSerializer(instance=user_list, many=False)return Response(ser.data, template_name='user_detail.html') views.py <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body>{{ user }}{{ pwd }}{{ ut }} </body> </html> userdetail.html

(5)瀏覽器格式API+JSON

訪問URL:

  • http://127.0.0.1:8000/test/?format=api
  • http://127.0.0.1:8000/test.api
  • http://127.0.0.1:8000/test/?
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializersfrom rest_framework.renderers import JSONRenderer from rest_framework.renderers import BrowsableAPIRendererfrom .. import modelsclass TestSerializer(serializers.ModelSerializer):class Meta:model = models.UserInfofields = "__all__"class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):def get_default_renderer(self, view):return JSONRenderer()class TestView(APIView):renderer_classes = [CustomBrowsableAPIRenderer, ]def get(self, request, *args, **kwargs):user_list = models.UserInfo.objects.all().first()ser = TestSerializer(instance=user_list, many=False)return Response(ser.data, template_name='user_detail.html') views.py

注意:如果同時多個存在時,自動根據URL后綴來選擇渲染器。

?

轉載于:https://www.cnblogs.com/yangmingxianshen/p/8847178.html

總結

以上是生活随笔為你收集整理的Django Rest Framework(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。