日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Django Rest Framework(一)

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

一、什么是RESTful

REST與技術(shù)無關(guān),代表一種軟件架構(gòu)風(fēng)格,REST是Representational State Transfer的簡稱,中文翻譯為“表征狀態(tài)轉(zhuǎn)移”。

REST從資源的角度審視整個網(wǎng)絡(luò),它將分布在網(wǎng)絡(luò)中某個節(jié)點的資源通過URL進行標(biāo)識,客戶端應(yīng)用通過URL來獲取資源的表征,獲取這些表征致使這些應(yīng)用轉(zhuǎn)變狀態(tài)。

所有的數(shù)據(jù),不管是通過網(wǎng)絡(luò)獲取的還是操作(增刪改查)的數(shù)據(jù)都是資源,將一切數(shù)據(jù)視為資源是REST區(qū)別于其他架構(gòu)風(fēng)格的最本質(zhì)屬性。

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

?

二、RESTful API設(shè)計

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

2.域名

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

3.路徑,視網(wǎng)絡(luò)上任何東西都是資源,均使用名詞表示(可復(fù)數(shù))

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

4.method

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

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

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

6.狀態(tài)碼

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

7.錯誤處理,狀態(tài)碼是4XX時,應(yīng)返回錯誤信息,error當(dāng)作key

{error: "Invalid API key" } View Code

8.返回結(jié)果,針對不同操作,服務(wù)器向用戶返回的結(jié)果應(yīng)該符合以下規(guī)范。

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

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

{"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實現(xiàn)

路由系統(tǒng):

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框架實現(xiàn)

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):"""請求到來之后,都要執(zhí)行dispatch方法,dispatch方法根據(jù)請求方式不同觸發(fā) get/post/put等方法注意:APIView中的dispatch方法有好多好多的功能"""return super().dispatch(request, *args, **kwargs)def get(self, request, *args, **kwargs):return Response('GET請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

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

?

2.認(rèn)證和授權(quán)

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

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):"""用戶認(rèn)證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認(rèn)證,默認(rèn)用戶和Token和使用配置文件進行設(shè)置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)表示驗證通過并設(shè)置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認(rèn)證失敗")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."""# 驗證失敗時,返回的響應(yīng)頭WWW-Authenticate對應(yīng)的值passclass TestView(APIView):authentication_classes = [TestAuthentication, ]permission_classes = []def get(self, request, *args, **kwargs):print(request.user)print(request.auth)return Response('GET請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(2)請求頭認(rèn)證

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):"""用戶認(rèn)證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認(rèn)證,默認(rèn)用戶和Token和使用配置文件進行設(shè)置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)表示驗證通過并設(shè)置用戶名和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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(3)多個認(rèn)證規(guī)則

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):"""用戶認(rèn)證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認(rèn)證,默認(rèn)用戶和Token和使用配置文件進行設(shè)置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認(rèn)值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認(rèn)值為:Noneelse:self.auth = None(user,token)表示驗證通過并設(shè)置用戶名和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):"""用戶認(rèn)證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認(rèn)證,默認(rèn)用戶和Token和使用配置文件進行設(shè)置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認(rèn)值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認(rèn)值為:Noneelse:self.auth = None(user,token)表示驗證通過并設(shè)置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認(rèn)證失敗")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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(4)認(rèn)證和權(quán)限

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):"""用戶認(rèn)證,如果驗證成功后返回元組: (用戶,用戶Token):param request: :return: None,表示跳過該驗證;如果跳過了所有認(rèn)證,默認(rèn)用戶和Token和使用配置文件進行設(shè)置self._authenticator = Noneif api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() # 默認(rèn)值為:匿名用戶else:self.user = Noneif api_settings.UNAUTHENTICATED_TOKEN:self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默認(rèn)值為:Noneelse:self.auth = None(user,token)表示驗證通過并設(shè)置用戶名和Token;AuthenticationFailed異常"""val = request.query_params.get('token')if val not in token_list:raise exceptions.AuthenticationFailed("用戶認(rèn)證失敗")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 = "權(quán)限驗證失敗"def has_permission(self, request, view):"""判斷是否有權(quán)限訪問當(dāng)前請求Return `True` if permission is granted, `False` otherwise.:param request: :param view: :return: True有權(quán)限;False無權(quán)限"""if request.user == "管理員":return True# GenericAPIView中g(shù)et_object時調(diào)用def has_object_permission(self, request, view, obj):"""視圖繼承GenericAPIView,并在其中使用get_object時獲取對象時,觸發(fā)單獨對象權(quán)限驗證Return `True` if permission is granted, `False` otherwise.:param request: :param view: :param obj: :return: True有權(quán)限;False無權(quán)限"""if request.user == "管理員":return Trueclass TestView(APIView):# 認(rèn)證的動作是由request.user觸發(fā)authentication_classes = [TestAuthentication, ]# 權(quán)限# 循環(huán)執(zhí)行所有的權(quán)限permission_classes = [TestPermission, ]def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

?

3.用戶訪問次數(shù)/頻率限制

(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):"""根據(jù)用戶IP和代理IP,當(dāng)做請求者的唯一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):"""是否仍然在允許范圍內(nèi)Return `True` if the request should be allowed, `False` otherwise.:param request: :param view: :return: True,表示可以通過;False表示已超過限制,不允許訪問"""# 獲取用戶唯一標(biāo)識(如: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):"""多少秒后可以允許繼續(xù)訪問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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容')def throttled(self, request, wait):"""訪問次數(shù)被限制時,定制錯誤信息"""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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容')def throttled(self, request, wait):"""訪問次數(shù)被限制時,定制錯誤信息"""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 對應(yīng)的頻率限制值throttle_scope = "xxxxxx"def get(self, request, *args, **kwargs):# self.dispatchprint(request.user)print(request.auth)return Response('GET請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容')def throttled(self, request, wait):"""訪問次數(shù)被限制時,定制錯誤信息"""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):"""匿名用戶,根據(jù)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):"""登錄用戶,根據(jù)用戶token限制"""scope = "luffy_user"def get_ident(self, request):"""認(rèn)證成功時: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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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', # 默認(rèn)版本'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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(2)基于url的正則方式

如:/v1/users/

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認(rèn)版本'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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(3)基于accept請求方式

如:Accept: application/json; version=1.0

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認(rèn)版本'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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

(4)基于主機名方法

如:v1.example.com

ALLOWED_HOSTS = ['*'] REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認(rèn)版本'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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

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

如:example.com/v1/users/

REST_FRAMEWORK = {'DEFAULT_VERSION': 'v1', # 默認(rèn)版本'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請求,響應(yīng)內(nèi)容')def post(self, request, *args, **kwargs):return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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)

根據(jù)請求頭content-type選擇對應(yīng)的解析器就請求體內(nèi)容處理。

(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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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

當(dāng)同時使用多個parser時,rest framework會更具請求頭content-type自動進行比對,并使用對應(yīng)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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') 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)# 獲取請求的值,并使用對應(yīng)的JSONParser進行處理print(request.data)# application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值print(request.POST)print(request.FILES)return Response('POST請求,響應(yīng)內(nèi)容')def put(self, request, *args, **kwargs):return Response('PUT請求,響應(yīng)內(nèi)容') views.py

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

?

6.序列化

序列化用于對用戶請求數(shù)據(jù)進行驗證和數(shù)據(jù)進行序列化。

(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."""# 執(zhí)行驗證之前調(diào)用,serializer_fields是當(dāng)前字段對象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):# 序列化,將數(shù)據(jù)庫查詢字段序列化為字典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):# 驗證,對請求發(fā)來的數(shù)據(jù)進行驗證ser = UserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應(yīng)內(nèi)容') 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."""# 執(zhí)行驗證之前調(diào)用,serializer_fields是當(dāng)前字段對象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):# 序列化,將數(shù)據(jù)庫查詢字段序列化為字典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):# 驗證,對請求發(fā)來的數(shù)據(jù)進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應(yīng)內(nèi)容') 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."""# 執(zhí)行驗證之前調(diào)用,serializer_fields是當(dāng)前字段對象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):# 序列化,將數(shù)據(jù)庫查詢字段序列化為字典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):# 驗證,對請求發(fā)來的數(shù)據(jù)進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應(yīng)內(nèi)容') 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."""# 執(zhí)行驗證之前調(diào)用,serializer_fields是當(dāng)前字段對象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):# # 序列化,將數(shù)據(jù)庫查詢字段序列化為字典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):# 驗證,對請求發(fā)來的數(shù)據(jù)進行驗證print(request.data)ser = ModelUserSerializer(data=request.data)if ser.is_valid():print(ser.validated_data)else:print(ser.errors)return Response('POST請求,響應(yīng)內(nèi)容') views.py

?

7.分頁

(1)根據(jù)頁碼進行分頁

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):# 默認(rèn)每頁顯示的數(shù)據(jù)條數(shù)page_size = 1# 獲取URL參數(shù)中設(shè)置的每頁顯示數(shù)據(jù)條數(shù)page_size_query_param = 'page_size'# 獲取URL參數(shù)中傳入的頁碼keypage_query_param = 'page'# 最大支持的每頁顯示的數(shù)據(jù)條數(shù)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')# 實例化分頁對象,獲取數(shù)據(jù)庫中的分頁數(shù)據(jù)paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數(shù)據(jù)response = paginator.get_paginated_response(serializer.data)return response views.py

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

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):# 默認(rèn)每頁顯示的數(shù)據(jù)條數(shù)default_limit = 10# URL中傳入的顯示數(shù)據(jù)條數(shù)的參數(shù)limit_query_param = 'limit'# URL中傳入的數(shù)據(jù)位置的參數(shù)offset_query_param = 'offset'# 最大每頁顯得條數(shù)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')# 實例化分頁對象,獲取數(shù)據(jù)庫中的分頁數(shù)據(jù)paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數(shù)據(jù)response = paginator.get_paginated_response(serializer.data)return response views.py

(3)游標(biāo)分頁

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傳入的游標(biāo)參數(shù)cursor_query_param = 'cursor'# 默認(rèn)每頁顯示的數(shù)據(jù)條數(shù)page_size = 2# URL傳入的每頁顯示條數(shù)的參數(shù)page_size_query_param = 'page_size'# 每頁顯示數(shù)據(jù)最大條數(shù)max_page_size = 1000# 根據(jù)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')# 實例化分頁對象,獲取數(shù)據(jù)庫中的分頁數(shù)據(jù)paginator = StandardResultsSetPagination()page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)# 序列化對象serializer = UserSerializer(page_user_list, many=True)# 生成分頁和數(shù)據(jù)response = paginator.get_paginated_response(serializer.data)return response views.py

?

8.路由系統(tǒng)

(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.渲染器

根據(jù)用戶請求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

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

?

轉(zhuǎn)載于:https://www.cnblogs.com/yangmingxianshen/p/8847178.html

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

九色91在线视频 | 国产一级大片在线观看 | 国产精品一区二区免费 | aav在线 | 免费久草视频 | 91亚洲精品久久久蜜桃 | 国产成人精品一区二区三区免费 | 2022国产精品视频 | 999久久久免费视频 午夜国产在线观看 | 久久久久一区二区三区 | 日韩精品一区二区三区免费观看视频 | 色综合天天色综合 | 在线亚洲播放 | 亚洲天堂香蕉 | 亚洲小视频在线 | 91在线porny国产在线看 | 国产 视频 久久 | 久久久久久草 | 国产精品18久久久久久不卡孕妇 | 久久精品国产亚洲a | 天天色天天骑天天射 | 天天鲁一鲁摸一摸爽一爽 | 不卡的一区二区三区 | 在线观看资源 | 国产中文在线视频 | 丝袜制服天堂 | www.激情五月.com | 成人毛片一区二区三区 | 亚洲欧美日韩在线一区二区 | 日韩草比 | av在线免费观看不卡 | 午夜美女视频 | 免费在线播放视频 | 五月婷婷综合在线视频 | 香蕉97视频观看在线观看 | 亚洲三级影院 | 麻豆va一区二区三区久久浪 | 91九色蝌蚪在线 | 中文字幕在线一区二区三区 | 九九在线国产视频 | 国产一区精品在线观看 | 最近中文字幕第一页 | 国产极品尤物在线 | 最近乱久中文字幕 | 五月婷婷另类国产 | 日韩欧美在线不卡 | 综合网天天色 | 欧美另类老妇 | 新av在线| 国产1区2区3区在线 亚洲自拍偷拍色图 | 九九九九精品九九九九 | 精品国产乱码久久 | 亚洲日本va在线观看 | 国产精品18久久久久vr手机版特色 | 麻豆精品视频在线 | 国内精品久久久久影院优 | 日韩在线理论 | 国产96精品 | 色姑娘综合 | 久久亚洲私人国产精品 | 日本韩国精品一区二区在线观看 | 在线电影日韩 | 国内三级在线 | 欧美色图视频一区 | av一级一片 | 亚洲免费精彩视频 | 成片视频免费观看 | 少妇精品久久久一区二区免费 | 中文字幕在线观看免费高清完整版 | 91人人在线 | 在线观看激情av | 免费看av在线 | 国产精品乱码久久久久 | 日韩在线首页 | 久久综合狠狠综合久久激情 | 九九热免费视频在线观看 | 中文字幕精品一区二区三区电影 | 天天射天天艹 | 91在线麻豆 | 亚州日韩中文字幕 | 网站在线观看日韩 | 天天操综合网 | 日韩夜夜爽| 在线韩国电影免费观影完整版 | 婷婷色吧 | 国产精品一区二区三区在线播放 | 午夜av免费观看 | 亚洲国产欧洲综合997久久, | 天天天操操操 | 久久国精品| 国产中文自拍 | 丁香婷婷色月天 | 久热爱| 久久99亚洲热视 | 国产黄在线观看 | 中文字幕在线观看资源 | 亚洲日日日 | 国产高清视频色在线www | 丰满少妇在线观看网站 | 激情文学综合丁香 | 久久成人综合视频 | 97视频在线观看成人 | 人人澡人人干 | 伊人春色电影网 | 久精品视频免费观看2 | 国产99久久精品一区二区300 | 久久综合欧美 | 日本精品视频一区二区 | 日本aaaa级毛片在线看 | 国产视频二区三区 | 超碰在线网 | 女人18片 | 亚洲va欧美va人人爽 | 天天曰夜夜操 | 日日夜夜精品视频天天综合网 | 国产黄色免费电影 | 色免费在线 | 国产精品乱码久久久久 | 天天射天天爱天天干 | 国产黄色免费 | 亚洲粉嫩av | 亚洲精品大片www | 97视频久久久| 人人看97 | 波多野结衣电影一区二区三区 | 热re99久久精品国产66热 | 欧美日韩在线免费观看视频 | 黄色片免费在线 | 九热在线 | 91在线看片 | 日韩免费一二三区 | 国产手机免费视频 | 在线观看av小说 | 国产精品美女 | 成人中文字幕在线观看 | 免费视频97| 日韩成人免费在线 | 夜夜骑日日操 | 欧美韩国日本在线观看 | 免费视频区 | 日韩免费三区 | 久久99中文字幕 | 美女黄频视频大全 | 中文永久免费观看 | 国产色就色 | 欧美黄色特级片 | 久草在线电影网 | 婷婷综合伊人 | www.五月天激情 | 亚洲一级性 | 成人av免费 | 超碰伊人网 | 久久久夜色 | 一本色道久久精品 | 精品国产免费一区二区三区五区 | 在线免费国产视频 | 成人免费大片黄在线播放 | 91原创在线观看 | 久一网站| 1区2区3区在线观看 三级动图 | 亚洲国产日韩欧美在线 | 亚洲国产欧美一区二区三区丁香婷 | 天天射天天操天天色 | 日韩69av| 日韩三级av | 免费黄色看片 | 偷拍精品一区二区三区 | 日本精品视频免费 | av电影在线免费观看 | 婷色| 91一区二区三区在线观看 | avwww在线| 91免费网址 | 97精品电影院| 亚洲精品一区中文字幕乱码 | 五月婷婷在线视频 | 成年人三级网站 | 亚洲国产日韩欧美在线 | 成人亚洲精品久久久久 | 西西人体www444 | 久久精品99 | 免费视频你懂的 | 久久久高清一区二区三区 | 国产黄色片久久久 | 啪一啪在线 | 九九九九热精品免费视频点播观看 | 日韩精品久久久久 | 国产亚洲精品久 | 国产精品免费不卡 | 久久96国产精品久久99软件 | 国产日产精品久久久久快鸭 | 天天干,天天干 | 成人91在线观看 | 在线小视频你懂得 | 麻豆成人网 | 亚洲视频资源在线 | 国产精品 视频 | 有码中文字幕在线观看 | 99在线视频网站 | 激情网站五月天 | 在线观看日韩 | 欧美一二三区播放 | 人人干人人艹 | 免费精品国产va自在自线 | 成年人在线免费看片 | 欧美色图亚洲图片 | 天天射天天射天天射 | 日韩有码在线播放 | 国产精品资源网 | 国产精品孕妇 | 日韩成人在线免费观看 | 欧美日本中文字幕 | 亚洲国产中文字幕在线视频综合 | 99久久99久久| 国产日韩精品在线 | 天天综合网 天天综合色 | 国产综合香蕉五月婷在线 | 成人国产精品 | 久草免费看 | 日韩av一区在线观看 | 亚洲aⅴ乱码精品成人区 | 亚洲精品视频大全 | 久久久久久久久久久久久影院 | 97视频在线免费观看 | 色资源在线 | 亚洲精品黄色在线观看 | 久久久久国产一区二区 | 免费av大全| 精品成人a区在线观看 | 深夜免费福利在线 | 欧美精品久久久久久久久久丰满 | 国产成人精品一区二区三区免费 | 五月天激情视频 | 国产精品亚洲人在线观看 | 亚洲精品午夜国产va久久成人 | 日韩三级视频在线看 | 精品久久久影院 | 欧美日韩国产精品一区二区亚洲 | 狠狠色伊人亚洲综合网站色 | 日本女人的性生活视频 | 奇米四色影狠狠爱7777 | 欧美一区二区日韩一区二区 | av7777777| 国产精品9区 | 欧美一级日韩三级 | 久草av在线播放 | 精品视频国产一区 | 亚洲成年人av| 国产免费亚洲 | 在线国产不卡 | 99re国产视频 | 干亚洲少妇 | 国产黄在线看 | 麻豆va一区二区三区久久浪 | 国产黄色片在线 | 亚洲日本国产 | 午夜精品一区二区三区在线视频 | 日韩 在线a | 五月天网站在线 | 国产一区二区三区黄 | www国产精品com| 永久免费视频国产 | 九九久 | 久综合网| 在线观看视频黄色 | 久久免费视频网站 | 国产精品自产拍在线观看桃花 | 91免费看黄 | 91av资源网 | 久久综合九色欧美综合狠狠 | 国产特级毛片aaaaaa | 日韩精品一区二区三区免费观看视频 | 在线成人短视频 | 精品欧美一区二区精品久久 | 免费福利视频导航 | 亚洲v欧美v国产v在线观看 | 久久蜜臀av | 最新成人在线 | 亚洲精品玖玖玖av在线看 | 毛片1000部免费看 | 亚洲婷久久 | 91视频电影 | 成人在线免费观看网站 | 国产亚洲成av人片在线观看桃 | 免费在线色 | 国产美女网站视频 | 99在线观看视频 | 香蕉在线影院 | 国产亚洲视频在线 | av高清一区| 天天干夜夜操视频 | 精品一区二区在线免费观看 | 国产日韩中文字幕 | 久久精品成人 | 国产一级片免费视频 | 久久国产精品成人免费浪潮 | 亚洲精品久久久久中文字幕m男 | 毛片网站观看 | 免费在线观看av的网站 | 国产精品 日韩 | 91片在线观看 | av在线免费观看黄 | 91麻豆精品国产91久久久无需广告 | 久久精品国产v日韩v亚洲 | 高清有码中文字幕 | 五月婷婷色综合 | 精品一区二区在线观看 | 久久理论电影网 | 中文字幕视频观看 | 日韩欧美第二页 | 黄色小说在线免费观看 | 超碰人人草人人 | 日韩精品无码一区二区三区 | 五月婷在线 | 日韩av成人在线 | 亚洲天堂网在线视频 | 91一区啪爱嗯打偷拍欧美 | 欧美日韩性视频 | 在线观看视频免费大全 | 国产高清视频色在线www | 成人午夜剧场在线观看 | 日本性高潮视频 | 亚洲精品网址在线观看 | 麻豆视频一区 | 国产91精品看黄网站 | 精品久久一二三区 | 国产一区视频在线 | 国产亚洲高清视频 | 成人av免费在线播放 | 99热精品在线 | 色婷婷亚洲综合 | 久久精品这里都是精品 | 午夜精品久久一牛影视 | 久久久久久精 | 久久免费视频这里只有精品 | 91.dizhi永久地址最新 | 久久久久成人免费 | 免费观看av | 久久国产色 | 97碰碰精品嫩模在线播放 | 国产精品成人一区二区三区吃奶 | 国产一区二区视频在线播放 | www激情久久 | 麻豆视频免费入口 | 亚洲综合欧美日韩狠狠色 | 久久久久婷 | 在线小视频国产 | 久久久精品日本 | 狠狠色丁香婷婷综合久小说久 | 97精品国产91久久久久久 | 伊人电影在线观看 | 丁香婷五月 | 日韩专区中文字幕 | 国产尤物在线视频 | japanesexxxhd奶水 91在线精品一区二区 | 国产黑丝袜在线 | 天天躁日日| 911久久| 国产高清视频色在线www | 成人四虎| 五月天色中色 | 天天做夜夜做 | 天天玩天天操天天射 | 欧美精品一区二区免费 | 91精品啪| 中文一区二区三区在线观看 | 亚洲精品777| 日本动漫做毛片一区二区 | 三级视频日韩 | 人人爱人人做人人爽 | 久久综合中文字幕 | 欧美日韩99| 国产高清免费 | 亚洲片在线观看 | 国产一区二区电影在线观看 | 免费av的网站 | 美女网站一区 | 亚州性色 | 亚洲专区中文字幕 | 亚洲国产精品一区二区尤物区 | 人人爽人人爽人人片av | 日本护士三级少妇三级999 | 亚洲精品网站在线 | 夜夜夜夜爽 | 特级西西人体444是什么意思 | 97人人网| 美女啪啪图片 | 国产精品福利一区 | 国产在线资源 | 国产中文字幕在线免费观看 | 日本在线视频一区二区三区 | 久久国产女人 | 91精品老司机久久一区啪 | 久久这里只有精品视频首页 | 色综合天天综合网国产成人网 | 国产亚洲精品中文字幕 | 亚洲婷婷丁香 | 欧美激情精品久久 | 日本黄色免费在线观看 | 91在线精品视频 | 日韩欧美有码在线 | 婷久久 | 国产99在线播放 | 国内成人av| 免费瑟瑟网站 | 精品一二三区 | 欧洲性视频 | 超碰在线日韩 | 日韩在线观看一区二区三区 | 99爱这里只有精品 | 99操视频 | av在线永久免费观看 | 中文字幕在线观看国产 | 伊人资源视频在线 | 国产视频每日更新 | 国产精品精品视频 | 国精产品999国精产 久久久久 | 黄色a在线观看 | 国产精品99爱 | 超碰在线94| 国产亚洲精品久久 | 综合国产在线观看 | 国产精品久久人 | 日韩欧美高清免费 | 国产69久久久欧美一级 | 99这里只有久久精品视频 | 欧美精品乱码99久久影院 | 国产一级片不卡 | 国产色女| 久久久久国产精品一区二区 | 欧美性生活久久 | 日韩欧美一区二区三区黑寡妇 | 97影视 | 国产综合香蕉五月婷在线 | 国产老妇av | 在线观看av大片 | 一区二区三区四区五区六区 | 中文字幕在线观看网站 | 久久精品日产第一区二区三区乱码 | 99视频在线精品国自产拍免费观看 | 叶爱av在线 | 久草在线费播放视频 | 亚洲综合色播 | 久久蜜臀av | adn—256中文在线观看 | 成人一区不卡 | 亚洲成av人影院 | 日韩欧美视频一区二区三区 | www.av中文字幕.com | 日本中文字幕电影在线免费观看 | 九九热精| 91视频免费视频 | 国产在线不卡视频 | 欧美高清成人 | 97视频网站 | 成人av免费在线观看 | 久久不卡国产精品一区二区 | 香蕉视频在线免费看 | 国产区精品区 | 97精品超碰一区二区三区 | 久久综合九色欧美综合狠狠 | 欧美日韩一二三四区 | 麻豆国产精品永久免费视频 | 手机看片久久 | 超碰免费97| 欧美视屏一区二区 | 99在线观看精品 | 免费观看久久久 | 人人插人人草 | www.夜夜爽| avove黑丝 | 日韩av专区| av免费在线网站 | 中文字幕国内精品 | 久久精品一区二区三区视频 | 国产精品第一视频 | 成人午夜剧场在线观看 | 国产一区高清在线观看 | 亚洲一二区视频 | 97超碰色偷偷 | 成人在线观看av | 久久久久久蜜av免费网站 | 国产91全国探花系列在线播放 | 天天色天天上天天操 | 碰超在线97人人 | 欧美一区二区三区四区夜夜大片 | 四虎永久免费 | 1000部18岁以下禁看视频 | 日韩三级一区 | 国产亚洲情侣一区二区无 | 国产一级片播放 | 久久国产电影 | 粉嫩av一区二区三区四区在线观看 | 美女免费视频一区 | 九七人人干 | 日韩高清免费在线观看 | 亚洲精选在线 | 中文字幕在线观看免费高清电影 | 国产99久久久久久免费看 | 国内精品久久久久影院优 | 日本久久精 | 美女黄频在线观看 | 日日日视频| 少妇bbb好爽 | 国产精品原创av片国产免费 | 天天操夜夜操国产精品 | 久精品在线 | 国产一区二区在线免费观看 | 日韩在线国产精品 | 热99久久精品 | 极品中文字幕 | 亚洲精品66 | a在线免费 | 麻豆精品视频在线观看免费 | 国产91精品一区二区绿帽 | 日本最新一区二区三区 | 日本一区二区免费在线观看 | 在线成人免费电影 | 一 级 黄 色 片免费看的 | 亚州激情视频 | 麻豆91在线观看 | 精品国产乱码久久久久 | 丰满少妇对白在线偷拍 | 日韩一级电影网站 | 亚洲综合爱 | 美女视频黄免费的 | 日韩激情视频在线 | 激情五月五月婷婷 | 天天插天天操天天干 | 亚洲精品国偷自产在线91正片 | 视频在线精品 | 久久久久久久av | 天天狠狠干 | 97av精品 | 丝袜制服天堂 | 欧美精品在线观看一区 | 午夜精品视频一区 | 亚州成人av在线 | 91av在线不卡 | 久久久毛片 | 国产一区免费视频 | .精品久久久麻豆国产精品 亚洲va欧美 | www最近高清中文国语在线观看 | 国产精品国产三级国产不产一地 | 久久久2o19精品 | 又黄又爽又刺激视频 | 天天看天天干 | 亚洲电影av在线 | 香蕉精品视频在线观看 | 天堂av网站| 999久久国产精品免费观看网站 | 亚洲视频一区二区三区在线观看 | 日本韩国精品在线 | 成人精品在线 | 97av超碰| 97视频精品 | 日本丶国产丶欧美色综合 | 久久手机免费视频 | 九九热有精品 | 久久久久久久久精 | 精品免费观看视频 | 91亚洲精品国产 | 天堂资源在线观看视频 | 久久久久伦理电影 | 久久婷婷视频 | 日韩免费福利 | 一区二区三区日韩精品 | 国内精品一区二区 | 日日摸日日添日日躁av | 日韩欧美网站 | 九九亚洲精品 | 777奇米四色 | 国产小视频在线免费观看视频 | 在线成人免费电影 | 久久伊人国产精品 | 亚洲精品欧美精品 | 欧美性精品 | 看av在线 | 国产日韩欧美在线一区 | 国产原创在线视频 | 天天鲁天天干天天射 | 91亚洲国产成人久久精品网站 | 久久涩视频 | 久久国产欧美日韩精品 | 亚洲精品1234区 | 欧美特一级片 | 久久免费视频一区 | 色99久久 | 色婷av | 国产精品入口66mio女同 | 五月开心综合 | 99av在线视频 | 久久这里只有精品久久 | 中文字幕在线观看你懂的 | 97香蕉久久超级碰碰高清版 | 一区二区视频在线看 | 一级久久久 | 精品国产一二三 | 日韩av三区| 91视频啪 | 麻豆视频免费入口 | 欧美一级性视频 | av免费福利 | 99re视频在线观看 | 国产精品免费视频一区二区 | av电影av在线 | 国产传媒中文字幕 | 国产日产高清dvd碟片 | 亚州欧美视频 | 国产亚洲精品免费 | 久久麻豆精品 | 免费视频97 | 天天干夜夜爽 | 国产精品理论在线观看 | 色综合夜色一区 | 在线播放日韩av | 韩国av电影在线观看 | 激情久久五月 | 日韩精品在线观看av | 精品久久久久免费极品大片 | 国产黄色片在线免费观看 | 9999国产| 中文字幕在线国产精品 | 人人狠| 精品一区二区免费视频 | 久久综合久久综合这里只有精品 | 久久精精品视频 | 国产人成一区二区三区影院 | 一区二区中文字幕在线观看 | 黄色毛片视频 | 少妇bbbb揉bbbb日本 | 久久视频这里有久久精品视频11 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 国产精品美女在线观看 | 午夜视频在线网站 | 欧美激情另类文学 | 久久精品久久精品久久精品 | 国产中文字幕精品 | 成人午夜精品福利免费 | 日韩乱码中文字幕 | 久久久亚洲国产精品麻豆综合天堂 | 97国产精品亚洲精品 | 五月婷婷开心 | 狠狠操狠狠干天天操 | 亚洲精品999 | 俺要去色综合狠狠 | 国产在线色视频 | 亚洲激情av| 一级黄色毛片 | 日韩精品一区二区三区在线视频 | 中文字幕亚洲精品在线观看 | 天天射综合网视频 | a√天堂中文在线 | av大全在线 | 国产999视频在线观看 | 国产美女精品 | 日日夜av| 国产精品手机在线 | 九九在线视频免费观看 | 91在线视频在线 | 996久久国产精品线观看 | 久久99精品国产麻豆婷婷 | 狠狠色伊人亚洲综合网站野外 | 91刺激视频 | www夜夜操| 免费在线观看日韩视频 | 天天色天天射综合网 | 伊人婷婷网 | 高清视频一区二区三区 | 国产成人高清在线 | 国产专区第一页 | 在线天堂v| 夜夜夜夜猛噜噜噜噜噜初音未来 | 99久久精品国产欧美主题曲 | 久久成人精品电影 | 色综合久久五月天 | 91丨九色丨蝌蚪丨对白 | 国产黑丝一区二区三区 | 欧美国产不卡 | 日本激情视频中文字幕 | 亚洲精品久久激情国产片 | 日韩黄色在线电影 | 草久久久久久 | 久久久精品一区二区三区 | 久久狠狠一本精品综合网 | 亚洲综合小说 | 婷婷色狠狠 | 中文乱幕日产无线码1区 | www.久久免费 | 国产.精品.日韩.另类.中文.在线.播放 | 成人在线观看av | 天天干天天做天天操 | 国产精品高潮呻吟久久久久 | 国产精品成人一区二区三区吃奶 | 亚洲成人第一区 | 波多野结衣小视频 | 久久99婷婷 | 人人插人人舔 | 一区二区三区在线电影 | 亚洲九九| 国产男女无遮挡猛进猛出在线观看 | 国产视频美女 | 国产精品久久久久永久免费观看 | 精品免费久久久久 | 国产青春久久久国产毛片 | 波多野结衣精品在线 | 新av在线| www在线观看视频 | 国产中文a | 久久精品国产精品亚洲 | 欧美精品一区在线发布 | 午夜影院在线观看18 | 国产精品黄网站在线观看 | 久草精品免费 | 麻豆mv在线观看 | 欧美日韩久久不卡 | 综合网伊人 | 天天爽天天碰狠狠添 | 天堂在线视频免费观看 | 在线99视频 | 一级性视频 | 日韩精品一区二区在线观看 | 国内精品视频免费 | 国产二区电影 | 在线观看免费高清视频大全追剧 | 97色免费视频 | 亚洲妇女av| 午夜黄色大片 | 国产成人精品一区二区 | 日韩首页 | 午夜影院在线观看18 | 成人91免费视频 | 成人av在线亚洲 | 久久艹国产 | 最近中文字幕免费大全 | 日韩电影在线一区 | 日韩精品一区二区三区在线播放 | 天天干天天射天天爽 | 91最新视频在线观看 | 日日夜日日干 | 国产精品6| 97成人在线视频 | 久久午夜精品视频 | 日韩美视频 | 热精品 | 亚洲在线视频免费观看 | 2024国产精品视频 | 99久久精品国 | 色噜噜色噜噜 | 国产成人三级三级三级97 | 日韩免费在线视频 | 这里有精品在线视频 | 91国内在线视频 | 日韩成人精品一区二区 | 欧美在线观看视频一区二区 | 97超碰在线资源 | 天天天插 | 亚洲国产成人精品在线观看 | 欧美色图另类 | 岛国大片免费视频 | 日韩69av| 国产白浆视频 | 黄色网大全| 成人蜜桃网 | 国产在线久久久 | 91在线精品秘密一区二区 | 在线视频久 | 在线免费观看羞羞视频 | 亚洲精品中文字幕视频 | 九色免费视频 | 日韩精品第1页 | 久久综合之合合综合久久 | 五月天六月色 | 奇米影视777四色米奇影院 | 久久精品视频播放 | 色欧美综合| 深夜免费网站 | 国产视频精品免费播放 | 中文字幕在线免费播放 | 中文字幕免费观看视频 | 国产精品乱码一区二三区 | 国产一二三区在线观看 | 在线看黄色av | 国产精品久久久久久久免费大片 | 久草在线在线精品观看 | wwwwww国产| 一区二区三区中文字幕在线观看 | 欧美日本中文字幕 | 久久久久国产一区二区三区 | 亚洲天天| 黄色片视频免费 | 天天拍天天爽 | 久久丁香| 黄a在线观看 | 色综合久久久久综合体 | 91视视频在线直接观看在线看网页在线看 | 91精品国产99久久久久久久 | 国产一区成人 | 色多多视频在线 | 中文在线字幕免 | 国产视频亚洲精品 | 国产精品一区二区三区在线播放 | 亚洲人成人99网站 | 啪啪凸凸| 日韩视频一区二区三区在线播放免费观看 | 麻豆视频www | 最近免费观看的电影完整版 | 国语精品视频 | 丁香花在线观看视频在线 | 粉嫩aⅴ一区二区三区 | 亚洲综合激情 | 九色porny真实丨国产18 | 国产青春久久久国产毛片 | 色天天综合久久久久综合片 | 亚洲精品国产精品国自产 | 色窝资源 | 国产 中文 日韩 欧美 | 日本久久久亚洲精品 | 国产在线精品二区 | 久久伦理网 | 久久视频免费在线 | 韩国av一区二区三区在线观看 | 不卡中文字幕在线 | 视频国产区 | 色婷婷激情网 | 99精品视频精品精品视频 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 玖草在线观看 | 色噜噜在线观看 | 国产精品久久久久久久久久久免费 | 国产精品原创视频 | 91电影福利 | 亚洲欧美在线综合 | 日韩精品中文字幕一区二区 | www.人人干| 国产成人精品午夜在线播放 | 香蕉视频久久久 | 在线а√天堂中文官网 | 国产91勾搭技师精品 | 91看毛片 | 美女精品 | www.99久久.com| 在线一区av | 国产青青青 | 免费亚洲一区二区 | 九七人人干 | 中文av网| 欧美一级性生活视频 | 在线观看国产高清视频 | av中文字幕日韩 | 黄色三级久久 | 97国产精品亚洲精品 | 黄色动态图xx | 狠狠色丁香九九婷婷综合五月 | 久久久久成人精品免费播放动漫 | 亚洲国产影院av久久久久 | 欧美激情精品久久久久久 | av永久网址 | 日韩一区在线免费观看 | 不卡av电影在线 | 亚洲另类在线视频 | 国产在线精品一区二区不卡了 | 欧美日韩高清 | 午夜黄色影院 | 欧美成人性战久久 | 亚洲在线免费视频 | 精品黄色视| 久久久在线 | 91久久久久久久一区二区 | 狠狠色狠狠色终合网 | 亚洲h视频在线 | 五月婷婷狠狠 | 成人午夜电影网站 | 狠狠色丁香久久婷婷综 | 在线免费性生活片 | 亚洲欧美视频在线播放 | 蜜臀av网址 | 国产女人18毛片水真多18精品 | 在线免费av网站 | 在线高清av | av播放在线 | 久久字幕精品一区 | 日韩免费视频在线观看 | 久久一区91 | 日韩性xxx| 日韩精品大片 | 91精品电影 | 欧美极品一区二区三区 | 91在线亚洲 | a√天堂资源 | 肉色欧美久久久久久久免费看 | 精品亚洲午夜久久久久91 | 国产精品24小时在线观看 | 99视频精品全国免费 | 国产精品视频区 | 亚洲国产欧洲综合997久久, | 手机在线小视频 | av高清网站在线观看 | 久久久久亚洲国产精品 | 99久久99视频 | 婷婷在线免费观看 | 五月开心婷婷 | 五月天综合色激情 | 午夜久久精品 | 亚洲精品99久久久久中文字幕 | 国产在线视频一区二区 | 久久久九色精品国产一区二区三区 | 久久精精品视频 | 久久久久久国产一区二区三区 | 手机色在线 | 91c网站色版视频 | 国产91在线观看 | 高清中文字幕 | 亚洲国产福利视频 | 欧美日韩不卡一区二区三区 | 免费av电影网站 | 欧美韩国在线 | 超碰97国产精品人人cao | 国产亚洲成av片在线观看 | 国产人免费人成免费视频 | 玖玖在线看 | 中文字幕亚洲国产 | 国产99久| 久草在线播放视频 | 成年人在线播放视频 | 三级av在线免费观看 | 欧美性极品xxxx做受 | 日本黄色免费播放 | 欧美一区二区三区在线 | 国产精品99久久久久久宅男 | av高清免费在线 | 久久精品国产一区二区电影 | 亚洲精品乱码久久久久v最新版 | 国产精品久久毛片 | 在线国产一区二区三区 | 日本三级国产 | 人人澡人摸人人添学生av | 91精品视频免费看 | 伊人中文网 | 手机看片国产日韩 | 啪啪资源| adc在线观看 | 99免费国产| 综合网五月天 | 69av在线视频 | 亚洲一区二区视频 | 成人av电影免费在线播放 | 久久在线免费观看视频 | 一级片在线 | 久久在线电影 | 久久综合婷婷国产二区高清 | 久草香蕉在线 | 日本黄色一级电影 | 在线导航av | 久草资源在线观看 | 欧美精品在线观看 | 四虎成人精品永久免费av | 欧美在线aaa | 一区二区三区不卡在线 | 综合网天天色 | 亚洲欧美视屏 | 中文字幕av免费 | 亚洲免费在线播放视频 | 欧美精品久久人人躁人人爽 | 亚洲成人家庭影院 | 波多野结衣小视频 | 久久综合狠狠综合久久综合88 | 97成人在线观看 | 美女视频一区 | 麻豆传媒视频观看 | www亚洲一区 | 天天插狠狠干 | 天天综合网天天综合色 | a特级毛片 | 99热亚洲精品 | 精品国产一区二区三区不卡 | 国产免费观看av | 午夜私人影院久久久久 | 91在线视频免费播放 | www.玖玖玖| 国产亚洲精品成人av久久ww | 久久精品一区二区 | 国产成人av一区二区三区在线观看 | 五月婷婷开心中文字幕 | 一级黄色免费网站 | 超碰97在线人人 | 日韩在线视频网 | 成人免费在线播放 | 97在线精品国自产拍中文 | 国产破处精品 | 日韩a在线播放 | 一区二区三区四区在线 | 午夜精品久久一牛影视 | 天天色天天艹 | 国产午夜精品福利视频 | 国产一级视频在线免费观看 | av在线直接看 | 91av视频观看 |