068.Python框架Django之DRF視圖集使用
一 視圖集與路由的使用
使用視圖集ViewSet,可以將一系列邏輯相關的動作放到一個類中:
-
list() 提供一組數據
-
retrieve() 提供單個數據
-
create() 創建數據
-
-
destory() 刪除數據
ViewSet視圖集類不再實現get()、post()等方法,而是實現動作 action 如 list() 、create() 等。
視圖集只在使用as_view()方法的時候,才會將action動作與具體請求方式對應上。
1.1 常用的視圖集父類
1 ViewSet
- 繼承自APIView 與 ViewSetMixin作用也與APIView基本類似,提供了身份認證、許可權校驗、流量管理等。
- ViewSet主要通過繼承ViewSetMixin來實現在調用as_view()時傳入字典(如{‘get’:’list’})的映射處理工作。
- 在ViewSet中,沒有提供任何動作action方法,需要我們自己實現action方法。
2 GenericViewSet
GenericViewSet就幫助我們完成了這樣的繼承工作,繼承自GenericAPIView與ViewSetMixin,在實現了調用as_view()時傳入字典(如{‘get’:’list’})的映射處理工作的同時,還提供了GenericAPIView提供的基礎方法,可以直接搭配Mixin擴展類使用。
3.ModelViewSet
繼承自GenericViewSet,同時包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4.ReadOnlyModelViewSet
繼承自GenericViewSet,同時包括了ListModelMixin、RetrieveModelMixin。
1.2 視圖集初步使用
創建一個子應用app
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# python3 manage.py startapp collect
註冊
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'students.apps.StudentsConfig', 'ser.apps.SerConfig', 'req.apps.ReqConfig', 'collect.apps.CollectConfig', ]
路由分發
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('student/',include("students.urls")), path('ser/',include("ser.urls")), path('req/', include("req.urls")), path('collect/', include("collect.urls")), ]
路由配置
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim collect/urls.py
from django.urls import path,re_path from collect import views urlpatterns = [ path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), ]
序列化文件
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim collect/serializers.py
from students.models import Student from rest_framework import serializers class StudentModelSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ["id", "name", "age", "sex"] extra_kwargs = { "name": {"max_length": 10, "min_length": 4}, "age": {"max_value": 150, "min_value": 0}, } def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "alex" and age == 22: raise serializers.ValidationError("alex在22時的故事。。。") return attrs
視圖文件
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data)
訪問//127.0.0.1:8000/collect/student1/可以獲取五條數據
資料庫中數據
mysql> select * from tb_student;
修改id=5的sex為false
資料庫現有數據
獲取5個男性的數據
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data)
配置路由
不要在同一個路由的as_view中書寫兩個同樣的鍵的http請求,會產生覆蓋!!!
from django.urls import path,re_path from collect import views urlpatterns = [ path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), ]
訪問//127.0.0.1:8000/collect/student1/get_5_female/結果如下
獲取一條
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), ]
配置視圖
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data)
POSTMAN調試,訪問//127.0.0.1:8000/collect/student1/5/
GenericViewSet視圖
URL路由配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), ]
視圖文件
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data)
POSTMAN調試
1.3 GenericViewSet結合模型類
可以和模型類進行組合快速生成基本的API介面
url路由配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面,當使用get,觸發list的方法,當使用POST請求,觸發create方法 path("students3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), ]
視圖文件
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer
POSTMAN調試
get請求
POST請求
查看資料庫
1.4 ModelViewSet配置
url配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面 path("student3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), # ModelViewSet 默認提供了5個API介面 path("student4/", views.Student5ModelViewSet.as_view({"post": "create", "get": "list"})), re_path(r"^student4/(?P<pk>\d+)/$", views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ]
views
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer
POSTMAN調試
獲取所有
POST添加
資料庫
PUT修改
資料庫
delete刪除
資料庫
mysql> select * from tb_student; +----+------------+-----+-----+------------+-------------------+ | id | name | sex | age | class_null | description | +----+------------+-----+-----+------------+-------------------+ | 1 | 令狐沖 | 1 | 18 | 205 | hello mysqlf | | 2 | 任我行 | 1 | 55 | 203 | hello let me go | | 3 | 李尋歡 | 1 | 33 | 207 | be happy lee | | 5 | limochu | 0 | 36 | 208 | Don』t Worry Lee | | 6 | mchaofeng | 1 | 26 | | | | 7 | yangguo | 1 | 25 | | | | 8 | xiaolongnv | 0 | 25 | | | +----+------------+-----+-----+------------+-------------------+
1.5 ReadOnlyModelViewSet配置
url路由配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面 path("student3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), # ModelViewSet 默認提供了5個API介面 path("student4/", views.Student5ModelViewSet.as_view({"post": "create", "get": "list"})), re_path(r"^student4/(?P<pk>\d+)/$", views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), # ReadOnlyModelViewSet path("student5/", views.Student6ReadOnlyModelViewSet.as_view({"get": "list"})), re_path(r"^student5/(?P<pk>\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})), ]
view視圖配置
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class Student6ReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer
只有get方法
獲取一條
二 路由類的使用
有了視圖集以後,視圖文件中多個視圖類可以合併成一個,但是,路由的程式碼就變得複雜了, 需要我們經常在as_view方法 ,編寫http請求和視圖方法的對應關係, 事實上,在路由中,DRF也提供了一個路由類給我們對路由的程式碼進行簡寫。 當然,這個路由類僅針對於 視圖集 才可以使用。
2.1 路由類基本配置
url路由配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面 path("student3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), # ModelViewSet 默認提供了5個API介面 path("student4/", views.Student5ModelViewSet.as_view({"post": "create", "get": "list"})), re_path(r"^student4/(?P<pk>\d+)/$", views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), # ReadOnlyModelViewSet path("student5/", views.Student6ReadOnlyModelViewSet.as_view({"get": "list"})), re_path(r"^student5/(?P<pk>\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})), ] # 路由類默認只會給視圖集中的基本5個API生成地址[ 獲取一條,獲取多條,添加.刪除,修改數據 ] from rest_framework.routers import DefaultRouter # 實例化路由類 router = DefaultRouter() # router.register("訪問地址前綴","視圖集類","訪問別名") # 註冊視圖視圖集類 router.register("student7", views.Student7ModelViewSet) print(router.urls) # 把路由列表註冊到django項目中 urlpatterns += router.urls
views視圖文件
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class Student6ReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.decorators import action class Student7ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer
重啟之後,查看print列印內容
[
<URLPattern '^student7/$' [name='student-list']>,
<URLPattern '^student7\.(?P<format>[a-z0-9]+)/?$' [name='student-list']>,
<URLPattern '^student7/(?P<pk>[^/.]+)/$' [name='student-detail']>,
<URLPattern '^student7/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='student-detail']>,
<URLPattern '^$' [name='api-root']>,
<URLPattern '^\.(?P<format>[a-z0-9]+)/?$' [name='api-root']>
]
POSTMAN調試
獲取所有
2.2 自定義方法並調用
添加進views方法中
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class Student6ReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.decorators import action class Student7ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer # methods 指定允許哪些http請求訪問當前視圖方法 # detail 指定生成的路由地址中是否要夾帶pk值,True為需要 # @action(methods=['get'], detail=False) # def get_4(self, request): @action(methods=['get'], detail=True) def get_5(self, request, pk): serilizer = self.get_serializer(instance=self.get_queryset().get(pk=pk)) return Response(serilizer.data)
重啟查看列印資訊
[
<URLPattern '^student7/$' [name='student-list']>,
<URLPattern '^student7\.(?P<format>[a-z0-9]+)/?$' [name='student-list']>,
<URLPattern '^student7/(?P<pk>[^/.]+)/$' [name='student-detail']>,
<URLPattern '^student7/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='student-detail']>,
<URLPattern '^student7/(?P<pk>[^/.]+)/get_5/$' [name='student-get-5']>,
<URLPattern '^student7/(?P<pk>[^/.]+)/get_5\.(?P<format>[a-z0-9]+)/?$' [name='student-get-5']>,
<URLPattern '^$' [name='api-root']>,
<URLPattern '^\.(?P<format>[a-z0-9]+)/?$' [name='api-root']>]
POSTMAN訪問自定義方法
2.3 在一個視圖類調用多個視圖劃器類
url路由配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面 path("student3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), # ModelViewSet 默認提供了5個API介面 path("student4/", views.Student5ModelViewSet.as_view({"post": "create", "get": "list"})), re_path(r"^student4/(?P<pk>\d+)/$", views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), # ReadOnlyModelViewSet path("student5/", views.Student6ReadOnlyModelViewSet.as_view({"get": "list"})), re_path(r"^student5/(?P<pk>\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})), # 一個視圖類中調用多個序列化器 path("student8/", views.Student8GenericAPIView.as_view()), ] # 路由類默認只會給視圖集中的基本5個API生成地址[ 獲取一條,獲取多條,添加.刪除,修改數據 ] from rest_framework.routers import DefaultRouter # 實例化路由類 router = DefaultRouter() # router.register("訪問地址前綴","視圖集類","訪問別名") # 註冊視圖視圖集類 router.register("student7", views.Student7ModelViewSet) print(router.urls) # 把路由列表註冊到django項目中 urlpatterns += router.urls
view視圖配置
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class Student6ReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.decorators import action class Student7ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer # methods 指定允許哪些http請求訪問當前視圖方法 # detail 指定生成的路由地址中是否要夾帶pk值,True為需要 # @action(methods=['get'], detail=False) # def get_4(self, request): @action(methods=['get'], detail=True) def get_5(self, request, pk): serilizer = self.get_serializer(instance=self.get_queryset().get(pk=pk)) return Response(serilizer.data) from rest_framework.generics import GenericAPIView from collect.serializers import StudentInfoModelSerializer class Student8GenericAPIView(GenericAPIView): queryset = Student.objects.all() # GenericAPI內部調用序列化器的方法,我們可以重寫這個方法來實現根據不同的需求來調用不同的序列化器 def get_serializer_class(self): if self.request.method == "GET": # 2個欄位 return StudentInfoModelSerializer return StudentModelSerializer def get(self, request): """獲取所有數據的id和name""" student_list = self.get_queryset() serializer = self.get_serializer(instance=student_list, many=True) # serializer = StudentInfoModelSerializer(instance=student_list, many=True) return Response(serializer.data) def post(self, request): """添加數據""" data = request.data serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data)
序列化類
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim collect/serializers.py
from students.models import Student from rest_framework import serializers class StudentModelSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ["id", "name", "age", "sex"] extra_kwargs = { "name": {"max_length": 10, "min_length": 4}, "age": {"max_value": 150, "min_value": 0}, } def validate_name(self, data): if data == "root": raise serializers.ValidationError("用戶名不能為root!") return data def validate(self, attrs): name = attrs.get('name') age = attrs.get('age') if name == "alex" and age == 22: raise serializers.ValidationError("alex在22時的故事。。。") return attrs class StudentInfoModelSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ["id", "name"]
訪問//127.0.0.1:8000/collect/student8/
只有兩個欄位
2.4 視圖集內使用多個序列化類
url配置
from django.urls import path,re_path from collect import views urlpatterns = [ #ViewSet path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})), path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})), re_path(r'^student1/(?P<pk>\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})), # GenericViewSet path('student2/', views.Student3GenericViewSet.as_view({"get": "get_5"})), path('student2/get_5_female/', views.Student3GenericViewSet.as_view({"get": "get_5_female"})), # GenericViewSet和模型類進行組合快速生成基本的API介面 path("student3/", views.Student4GenericViewSet.as_view({"get": "list", "post": "create"})), # ModelViewSet 默認提供了5個API介面 path("student4/", views.Student5ModelViewSet.as_view({"post": "create", "get": "list"})), re_path(r"^student4/(?P<pk>\d+)/$", views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), # ReadOnlyModelViewSet path("student5/", views.Student6ReadOnlyModelViewSet.as_view({"get": "list"})), re_path(r"^student5/(?P<pk>\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})), # 一個視圖類中調用多個序列化器 path("student8/", views.Student8GenericAPIView.as_view()), # 一個視圖集中調用多個序列化器 path("student9/", views.Student9ModelViewSet.as_view({"get": "list"})), re_path(r"^student9/(?P<pk>\d+)/$", views.Student9ModelViewSet.as_view({"get": "retrieve"})), ] # 路由類默認只會給視圖集中的基本5個API生成地址[ 獲取一條,獲取多條,添加.刪除,修改數據 ] from rest_framework.routers import DefaultRouter # 實例化路由類 router = DefaultRouter() # router.register("訪問地址前綴","視圖集類","訪問別名") # 註冊視圖視圖集類 router.register("student7", views.Student7ModelViewSet) print(router.urls) # 把路由列表註冊到django項目中 urlpatterns += router.urls
views配置
要求:
- 列表數據list,返回2個欄位,
- 詳情數據retrieve,返回所有欄位
from django.shortcuts import render from rest_framework.viewsets import ViewSet from students.models import Student from collect.serializers import StudentModelSerializer from rest_framework.response import Response # Create your views here. class Student1ViewSet(ViewSet): def get_5(self,request): #取出所有,並切片操作 queryset = Student.objects.all()[:5] #實例化 serializer = StudentModelSerializer(instance=queryset,many=True) return Response(serializer.data) def get_5_female(self,request): queryset = Student.objects.filter(sex=False)[:5] serializer = StudentModelSerializer(instance=queryset, many=True) return Response(serializer.data) def get_one(self,request,pk): student_obj = Student.objects.get(pk=pk) serializer = StudentModelSerializer(instance=student_obj) return Response(serializer.data) from rest_framework.viewsets import GenericViewSet class Student3GenericViewSet(GenericViewSet): serializer_class = StudentModelSerializer queryset = Student.objects.all() def get_5(self, request): student_list = self.get_queryset()[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) def get_5_female(self, request): student_list = self.get_queryset().filter(sex=False)[:5] serializer = self.get_serializer(instance=student_list, many=True) return Response(serializer.data) from rest_framework.mixins import ListModelMixin, CreateModelMixin class Student4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ModelViewSet class Student5ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.viewsets import ReadOnlyModelViewSet class Student6ReadOnlyModelViewSet(ReadOnlyModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer from rest_framework.decorators import action class Student7ModelViewSet(ModelViewSet): queryset = Student.objects.all() serializer_class = StudentModelSerializer # methods 指定允許哪些http請求訪問當前視圖方法 # detail 指定生成的路由地址中是否要夾帶pk值,True為需要 # @action(methods=['get'], detail=False) # def get_4(self, request): @action(methods=['get'], detail=True) def get_5(self, request, pk): serilizer = self.get_serializer(instance=self.get_queryset().get(pk=pk)) return Response(serilizer.data) from rest_framework.generics import GenericAPIView from collect.serializers import StudentInfoModelSerializer class Student8GenericAPIView(GenericAPIView): queryset = Student.objects.all() # GenericAPI內部調用序列化器的方法,我們可以重寫這個方法來實現根據不同的需求來調用不同的序列化器 def get_serializer_class(self): if self.request.method == "GET": # 2個欄位 return StudentInfoModelSerializer return StudentModelSerializer def get(self, request): """獲取所有數據的id和name""" student_list = self.get_queryset() serializer = self.get_serializer(instance=student_list, many=True) # serializer = StudentInfoModelSerializer(instance=student_list, many=True) return Response(serializer.data) def post(self, request): """添加數據""" data = request.data serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data) class Student9ModelViewSet(ModelViewSet): queryset = Student.objects.all() def get_serializer_class(self): # 本次客戶端請求的視圖方法名 self.action print(self.action) if self.action == "list": return StudentInfoModelSerializer return StudentModelSerializer
get獲取所有,只返回兩個欄位
列印的結果是list
輸出單個資訊,會輸出4個欄位
方法名稱
三 DRF的擴展功能
創建新的app應用
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# python3 manage.py startapp opt
註冊
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'students.apps.StudentsConfig', 'ser.apps.SerConfig', 'req.apps.ReqConfig', 'collect.apps.CollectConfig', 'opt.apps.OptConfig', ]
配置字體
LANGUAGE_CODE = 'zh-hans'
添加路由分發
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('student/',include("students.urls")), path('ser/',include("ser.urls")), path('req/', include("req.urls")), path('collect/', include("collect.urls")), path('opt/', include("opt.urls")), ]
3.1 用戶控制
創建路由文件
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim opt/urls.py
from django.urls import path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), ]
views文件
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2")
創建一個admin用戶進行管理
登錄//127.0.0.1:8000/admin/login/?next=/admin/
登陸後,查看//127.0.0.1:8000/opt/auth1/和 //127.0.0.1:8000/opt/auth2/
創建一個alex用戶
使用alex登錄,同時取消人員狀態
然後auth1可以正常訪問,但是訪問//127.0.0.1:8000/opt/auth2/
必須是一個超級管理員用戶才能看見
查看數據的seeeion
mysql> select * from django_session;
+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+ | session_key | session_data | expire_date | +----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+ | fn55zqveedvfjckalewwusqny7iadhun | MWM5NDBiNmI0ZDZlYTFmZmM4MjE4YTkyODcyMWNmNTQ4NjJkNDJkNTp7Il9hdXRoX3VzZXJfaWQiOiIyIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiIwMTY2ZDUxMTFhYzU2ZTBjMWRkZDU5ZmM3MmE5ZmI1ZjcyYWY4NmMxIn0= | 2020-05-05 07:27:10.353593 | +----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+
許可權控制可以限制用戶對於視圖的訪問和對於具體數據對象的訪問。
-
在執行視圖的dispatch()方法前,會先進行視圖訪問許可權的判斷
-
在通過get_object()獲取具體對象時,會進行模型對象訪問許可權的判斷
內置提供的許可權:
-
AllowAny 允許所有用戶
-
IsAuthenticated 僅通過認證的用戶
-
IsAdminUser 僅管理員用戶
-
IsAuthenticatedOrReadOnly 已經登陸認證的用戶可以對數據進行增刪改操作,沒有登陸認證的只能查看數據。
可以在配置文件中全局設置默認的許可權管理類,如:
REST_FRAMEWORK = { .... 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
如果未指明,則採用如下默認配置
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny',
自定義許可權
url配置
from django.urls import path,re_path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), # 自定義許可權 path('auth3/', views.Demo3APIView.as_view()), ]
views配置
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2") # 自定義許可權 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): def has_permission(self, request, view): """ 針對訪問視圖進行許可權判斷 :param request: 本次操作的http請求對象 :param view: 本次訪問路由對應的視圖對象 :return: """ if request.user.username == "xiaoming": return True return False class Demo3APIView(APIView): permission_classes = [MyPermission] def get(self, request): """個人中心3""" return Response("個人中心3")
創建xiaoming用戶
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# python3 manage.py createsuperuser
使用root登錄訪問auth3
使用ixaoming用戶登錄訪問
3.3 限流Throttling
可以對介面訪問的頻次進行限制,以減輕伺服器壓力。
一般用於付費購買次數,投票等場景使用.
可以在配置文件中,使用DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES進行全局配置
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# vim drf_demo/settings.py
REST_FRAMEWORK = { # 限流 'DEFAULT_THROTTLE_CLASSES': ( # 對全局進行設置 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ), 'DEFAULT_THROTTLE_RATES': { 'anon': '3/hour', 'user': '3/minute', } }
DEFAULT_THROTTLE_RATES 可以使用 second, minute, hour 或day來指明周期。
URL文件
from django.urls import path,re_path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), # 自定義許可權 path('auth3/', views.Demo3APIView.as_view()), # 限流 path('auth4/', views.Demo4APIView.as_view()), ]
views視圖文件
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2") # 自定義許可權 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): def has_permission(self, request, view): """ 針對訪問視圖進行許可權判斷,必須使用xiaoming用戶 :param request: 本次操作的http請求對象 :param view: 本次訪問路由對應的視圖對象 :return: """ if request.user.username == "xiaoming": return True return False class Demo3APIView(APIView): permission_classes = [MyPermission] def get(self, request): """個人中心3""" return Response("個人中心3") # 限流 from rest_framework.throttling import UserRateThrottle, AnonRateThrottle class Demo4APIView(APIView): throttle_classes = [UserRateThrottle, AnonRateThrottle] # 全局配置後,這裡就不用指定 def get(self, request): """投票頁面""" return Response("投票頁面")
訪問auth4
當超過3次
註銷用戶,使用匿名用戶次數超標
3.4 過濾Filtering
對於列表數據可能需要根據欄位進行過濾,我們可以通過添加django-fitlter擴展來增強支援。
安裝django
-
filter
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# pip3 install django-filter
註冊
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'django_filters', # 需要註冊應用, 'students.apps.StudentsConfig', 'ser.apps.SerConfig', 'req.apps.ReqConfig', 'collect.apps.CollectConfig', 'opt.apps.OptConfig', ]
配置url路由
from django.urls import path,re_path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), # 自定義許可權 path('auth3/', views.Demo3APIView.as_view()), # 限流 path('auth4/', views.Demo4APIView.as_view()), # 過濾 path('data5/', views.Demo5APIView.as_view()), ]
views視圖
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2") # 自定義許可權 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): def has_permission(self, request, view): """ 針對訪問視圖進行許可權判斷,必須使用xiaoming用戶 :param request: 本次操作的http請求對象 :param view: 本次訪問路由對應的視圖對象 :return: """ if request.user.username == "xiaoming": return True return False class Demo3APIView(APIView): permission_classes = [MyPermission] def get(self, request): """個人中心3""" return Response("個人中心3") # 限流 from rest_framework.throttling import UserRateThrottle, AnonRateThrottle class Demo4APIView(APIView): throttle_classes = [UserRateThrottle, AnonRateThrottle] # 全局配置後,這裡就不用指定 def get(self, request): """投票頁面""" return Response("投票頁面") # 過濾 from rest_framework.generics import GenericAPIView, ListAPIView from students.models import Student from opt.serializers import StudentModelSerializer from django_filters.rest_framework import DjangoFilterBackend # 'django_filters.rest_framework.DjangoFilterBackend' class Demo5APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [DjangoFilterBackend] # 全局配置後,這裡就不用指定了。 filter_fields = ['age', "id"] # 聲明過濾欄位
複製一個序列化類
(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# cp collect/serializers.py opt/
setting設置
REST_FRAMEWORK = { # 限流 'DEFAULT_THROTTLE_CLASSES': ( # 對全局進行設置 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ), 'DEFAULT_THROTTLE_RATES': { 'anon': '3/hour', 'user': '3/minute', } 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) }
點擊過濾器
提交
3.5 排序Ordering
對於列表數據,REST framework提供了OrderingFilter過濾器來幫助我們快速指明數據按照指定欄位進行排序。
使用方法:
在類視圖中設置filter_backends,使用rest_framework.filters.OrderingFilter過濾器,REST framework會在請求的查詢字元串參數中檢查是否包含了ordering參數,如果包含了ordering參數,則按照ordering參數指明的排序欄位對數據集進行排序。
前端可以傳遞的ordering參數的可選欄位值需要在ordering_fields中指明。
路由配置
from django.urls import path,re_path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), # 自定義許可權 path('auth3/', views.Demo3APIView.as_view()), # 限流 path('auth4/', views.Demo4APIView.as_view()), # 過濾 path('data5/', views.Demo5APIView.as_view()), # 排序 path('data6/', views.Demo6APIView.as_view()), ]
views視圖配置
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2") # 自定義許可權 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): def has_permission(self, request, view): """ 針對訪問視圖進行許可權判斷,必須使用xiaoming用戶 :param request: 本次操作的http請求對象 :param view: 本次訪問路由對應的視圖對象 :return: """ if request.user.username == "xiaoming": return True return False class Demo3APIView(APIView): permission_classes = [MyPermission] def get(self, request): """個人中心3""" return Response("個人中心3") # 限流 from rest_framework.throttling import UserRateThrottle, AnonRateThrottle class Demo4APIView(APIView): throttle_classes = [UserRateThrottle, AnonRateThrottle] # 全局配置後,這裡就不用指定 def get(self, request): """投票頁面""" return Response("投票頁面") # 過濾 from rest_framework.generics import GenericAPIView, ListAPIView from students.models import Student from opt.serializers import StudentModelSerializer from django_filters.rest_framework import DjangoFilterBackend # 'django_filters.rest_framework.DjangoFilterBackend' class Demo5APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [DjangoFilterBackend] # 全局配置後,這裡就不用指定了。 filter_fields = ['age', "id"] # 聲明過濾欄位 # 排序 from rest_framework.filters import OrderingFilter class Demo6APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [DjangoFilterBackend, OrderingFilter] # 局部配置會覆蓋全局配置 filter_fields = ['id', "sex"] ordering_fields = ['id', "age"]
點擊過濾器
3.6 分頁Pagination
REST framework提供了分頁的支援。
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 # 每頁數目 }
也可通過自定義Pagination類,來為視圖添加不同分頁行為。在視圖中通過pagination_clas屬性來指明。
opt下的urls.py
from django.urls import path,re_path from opt import views urlpatterns = [ path('auth1/', views.Demo1APIView.as_view()), path('auth2/', views.Demo2APIView.as_view()), # 自定義許可權 path('auth3/', views.Demo3APIView.as_view()), # 限流 path('auth4/', views.Demo4APIView.as_view()), # 過濾 path('data5/', views.Demo5APIView.as_view()), # 排序 path('data6/', views.Demo6APIView.as_view()), # 分頁 path('data7/', views.Demo7APIView.as_view()), ]
views視圖文件
from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated, IsAdminUser #用戶的認證和許可權識別 class Demo1APIView(APIView): #只允許登錄後的用戶訪問 permission_classes = [IsAuthenticated] def get(self, request): #個人中心 return Response("個人中心") class Demo2APIView(APIView): #只允許管理員訪問 permission_classes = [IsAdminUser] def get(self, request): #個人中心2 return Response("個人中心2") # 自定義許可權 from rest_framework.permissions import BasePermission class MyPermission(BasePermission): def has_permission(self, request, view): """ 針對訪問視圖進行許可權判斷,必須使用xiaoming用戶 :param request: 本次操作的http請求對象 :param view: 本次訪問路由對應的視圖對象 :return: """ if request.user.username == "xiaoming": return True return False class Demo3APIView(APIView): permission_classes = [MyPermission] def get(self, request): """個人中心3""" return Response("個人中心3") # 限流 from rest_framework.throttling import UserRateThrottle, AnonRateThrottle class Demo4APIView(APIView): throttle_classes = [UserRateThrottle, AnonRateThrottle] # 全局配置後,這裡就不用指定 def get(self, request): """投票頁面""" return Response("投票頁面") # 過濾 from rest_framework.generics import GenericAPIView, ListAPIView from students.models import Student from opt.serializers import StudentModelSerializer from django_filters.rest_framework import DjangoFilterBackend # 'django_filters.rest_framework.DjangoFilterBackend' class Demo5APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [DjangoFilterBackend] # 全局配置後,這裡就不用指定了。 filter_fields = ['age', "id"] # 聲明過濾欄位 # 排序 from rest_framework.filters import OrderingFilter class Demo6APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [DjangoFilterBackend, OrderingFilter] # 局部配置會覆蓋全局配置 filter_fields = ['id', "sex"] ordering_fields = ['id', "age"] #分頁 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination """1. 自定義分頁器,訂製分頁的相關配置""" """ # 頁碼分頁 PageNumberPagination 前端訪問形式:GET //127.0.0.1:8000/opt/data7/?page=4 page=1 limit 0,10 page=2 limit 10,20 # 偏移量分頁 LimitOffsetPagination 前端訪問形式:GET //127.0.0.1:8000/opt/data7/?start=4&size=3 start=0 limit 0,10 start=10 limit 10,10 start=20 limit 20,10 """ class StandardPageNumberPagination(PageNumberPagination): """分頁相關配置""" page_query_param = "page" # 設置分頁頁碼關鍵字名 page_size = 3 # 設置每頁顯示數據條數 page_size_query_param = "size" # 設置指定每頁大小的關鍵字名 max_page_size = 5 # 設置每頁顯示最大值 class StandardLimitOffsetPagination(LimitOffsetPagination): default_limit = 2 # 默認限制,默認值與PAGE_SIZE設置一致 limit_query_param = "size" # limit參數名 offset_query_param = "start" # offset參數名 max_limit = 5 # 最大limit限制 class Demo7APIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer # 分頁 # 頁碼分頁類 pagination_class = StandardPageNumberPagination # 偏移量分頁類 # pagination_class = StandardLimitOffsetPagination
訪問//127.0.0.1:8000/opt/data7/?page=1&size=8,就是每一頁顯示8個數據
但是只顯示五個,是在程式碼設置最大顯示5個,當設置顯示8個時,不會生效,只會顯示5個
參考://www.cnblogs.com/Michael–chen/p/11222143.html,老男孩教育://www.oldboyedu.com/