java中fitlter,068.Python框架Django之DRF视图集使用

一 视图集与路由的使用

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

list() 提供一组数据

retrieve() 提供单个数据

create() 创建数据

update() 保存数据

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

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView。

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 importadminfrom django.urls importpath,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 importpath,re_pathfrom collect importviews

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 importStudentfrom rest_framework importserializersclassStudentModelSerializer(serializers.ModelSerializer):classMeta:

model=Student

fields= ["id", "name", "age", "sex"]

extra_kwargs={"name": {"max_length": 10, "min_length": 4},"age": {"max_value": 150, "min_value": 0},

}defvalidate_name(self, data):if data == "root":raise serializers.ValidationError("用户名不能为root!")returndatadefvalidate(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 importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)return Response(serializer.data)

访问http://127.0.0.1:8000/collect/student1/可以获取五条数据

70d5da0033a59957dc26834e8f03907f.png

数据库中数据

mysql> select * from tb_student;

5177086256d5ed988fdf68b62ce03da5.png

修改id=5的sex为false

数据库现有数据

bc6a36676db70aaad4b7132c5a6a5f27.png

获取5个男性的数据

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_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 importpath,re_pathfrom collect importviews

urlpatterns=[

path('student1/', views.Student1ViewSet.as_view({"get": "get_5"})),

path('student1/get_5_female/', views.Student1ViewSet.as_view({"get": "get_5_female"})),

]

访问http://127.0.0.1:8000/collect/student1/get_5_female/结果如下

dd717e8dc40b077f2225bc8cd9561eec.png

获取一条

from django.urls importpath,re_pathfrom collect importviews

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\d+)/$', views.Student1ViewSet.as_view({"get": "get_one"})),

]

配置视图

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)return Response(serializer.data)

POSTMAN调试,访问http://127.0.0.1:8000/collect/student1/5/

a64f189f3ff9da321c55d65964e6ca83.png

GenericViewSet视图

URL路由配置

from django.urls importpath,re_pathfrom collect importviews

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\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 importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_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调试

a5f4adb9deae89690509f82801c601c0.png

d2a9beba3b29904ef460d5b80619abed.png

1.3 GenericViewSet结合模型类

可以和模型类进行组合快速生成基本的API接口

url路由配置

from django.urls importpath,re_pathfrom collect importviews

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\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 importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class= StudentModelSerializer

POSTMAN调试

get请求

955de75b54ef3ffa70a56375410faa16.png

POST请求

90323b57a76169f07585ed9b4ace2c95.png

查看数据库

b52713ff6ad90a7101c42ed9824c7786.png

1.4 ModelViewSet配置

url配置

from django.urls importpath,re_pathfrom collect importviews

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\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\d+)/$",

views.Student5ModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

]

views

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importModelViewSetclassStudent5ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class= StudentModelSerializer

POSTMAN调试

获取所有

09a0e09a26853a70e877e07e30f4d6ff.png

POST添加

621be891a203cd0d0d989b5e0685913e.png

数据库

970192087822b7ba9f6f1c78cf162700.png

PUT修改

206f18bd7c28177b293b5db315423f88.png

数据库

ade4a8fc55a987f728d8c5c780fc5cff.png

delete删除

d5bc65a3516ef61e79d178b4849c6be9.png

数据库

mysql> select * fromtb_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 importpath,re_pathfrom collect importviews

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\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\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\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})),

]

view视图配置

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importModelViewSetclassStudent5ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importReadOnlyModelViewSetclassStudent6ReadOnlyModelViewSet(ReadOnlyModelViewSet):

queryset=Student.objects.all()

serializer_class= StudentModelSerializer

只有get方法

751219f35c4e4634b620fbb568132fe0.png

获取一条

41d1d8bfb52340defe6577228d866557.png

二 路由类的使用

有了视图集以后,视图文件中多个视图类可以合并成一个,但是,路由的代码就变得复杂了, 需要我们经常在as_view方法 ,编写http请求和视图方法的对应关系, 事实上,在路由中,DRF也提供了一个路由类给我们对路由的代码进行简写。 当然,这个路由类仅针对于 视图集 才可以使用。

2.1 路由类基本配置

url路由配置

from django.urls importpath,re_pathfrom collect importviews

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\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\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\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})),

]#路由类默认只会给视图集中的基本5个API生成地址[ 获取一条,获取多条,添加.删除,修改数据 ]

from rest_framework.routers importDefaultRouter#实例化路由类

router =DefaultRouter()#router.register("访问地址前缀","视图集类","访问别名")#注册视图视图集类

router.register("student7", views.Student7ModelViewSet)print(router.urls)#把路由列表注册到django项目中

urlpatterns += router.urls

views视图文件

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets import ModelViewSet

class Student5ModelViewSet(ModelViewSet):

queryset = Student.objects.all()

serializer_class = StudentModelSerializerfrom rest_framework.viewsets importReadOnlyModelViewSetclassStudent6ReadOnlyModelViewSet(ReadOnlyModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.decorators importactionclassStudent7ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class= StudentModelSerializer

重启之后,查看print打印内容

[

,

[a-z0-9]+)/?$' [name='student-list']>,

[^/.]+)/$' [name='student-detail']>,

[^/.]+)\.(?P[a-z0-9]+)/?$' [name='student-detail']>,

,

[a-z0-9]+)/?$' [name='api-root']>

]

POSTMAN调试

获取所有

df0e25f74f20995826a1b50e49aa3c98.png

2.2 自定义方法并调用

添加进views方法中

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importModelViewSetclassStudent5ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importReadOnlyModelViewSetclassStudent6ReadOnlyModelViewSet(ReadOnlyModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.decorators importactionclassStudent7ModelViewSet(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)

重启查看打印信息

[

,

[a-z0-9]+)/?$' [name='student-list']>,

[^/.]+)/$' [name='student-detail']>,

[^/.]+)\.(?P[a-z0-9]+)/?$' [name='student-detail']>,

[^/.]+)/get_5/$' [name='student-get-5']>,

[^/.]+)/get_5\.(?P[a-z0-9]+)/?$' [name='student-get-5']>,

,

[a-z0-9]+)/?$' [name='api-root']>]

POSTMAN访问自定义方法

5864f37bbfc51bb4427ed97fac5552d3.png

2.3 在一个视图类调用多个视图划器类

url路由配置

from django.urls importpath,re_pathfrom collect importviews

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\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\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\d+)/$", views.Student6ReadOnlyModelViewSet.as_view({"get": "retrieve"})),#一个视图类中调用多个序列化器

path("student8/", views.Student8GenericAPIView.as_view()),

]#路由类默认只会给视图集中的基本5个API生成地址[ 获取一条,获取多条,添加.删除,修改数据 ]

from rest_framework.routers importDefaultRouter#实例化路由类

router =DefaultRouter()#router.register("访问地址前缀","视图集类","访问别名")#注册视图视图集类

router.register("student7", views.Student7ModelViewSet)print(router.urls)#把路由列表注册到django项目中

urlpatterns += router.urls

view视图配置

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importModelViewSetclassStudent5ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importReadOnlyModelViewSetclassStudent6ReadOnlyModelViewSet(ReadOnlyModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.decorators importactionclassStudent7ModelViewSet(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)defget_5(self, request, pk):

serilizer= self.get_serializer(instance=self.get_queryset().get(pk=pk))returnResponse(serilizer.data)from rest_framework.generics importGenericAPIViewfrom collect.serializers importStudentInfoModelSerializerclassStudent8GenericAPIView(GenericAPIView):

queryset=Student.objects.all()#GenericAPI内部调用序列化器的方法,我们可以重写这个方法来实现根据不同的需求来调用不同的序列化器

defget_serializer_class(self):if self.request.method == "GET":#2个字段

returnStudentInfoModelSerializerreturnStudentModelSerializerdefget(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)

returnResponse(serializer.data)defpost(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 importStudentfrom rest_framework importserializersclassStudentModelSerializer(serializers.ModelSerializer):classMeta:

model=Student

fields= ["id", "name", "age", "sex"]

extra_kwargs={"name": {"max_length": 10, "min_length": 4},"age": {"max_value": 150, "min_value": 0},

}defvalidate_name(self, data):if data == "root":raise serializers.ValidationError("用户名不能为root!")returndatadefvalidate(self, attrs):

name= attrs.get('name')

age= attrs.get('age')if name == "alex" and age == 22:raise serializers.ValidationError("alex在22时的故事。。。")returnattrsclassStudentInfoModelSerializer(serializers.ModelSerializer):classMeta:

model=Student

fields= ["id", "name"]

访问http://127.0.0.1:8000/collect/student8/

只有两个字段

f851b672dc87308c72a12833ca546923.png

2.4 视图集内使用多个序列化类

url配置

from django.urls importpath,re_pathfrom collect importviews

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\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\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\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\d+)/$", views.Student9ModelViewSet.as_view({"get": "retrieve"})),

]#路由类默认只会给视图集中的基本5个API生成地址[ 获取一条,获取多条,添加.删除,修改数据 ]

from rest_framework.routers importDefaultRouter#实例化路由类

router =DefaultRouter()#router.register("访问地址前缀","视图集类","访问别名")#注册视图视图集类

router.register("student7", views.Student7ModelViewSet)print(router.urls)#把路由列表注册到django项目中

urlpatterns += router.urls

views配置

要求:

列表数据list,返回2个字段,

详情数据retrieve,返回所有字段

from django.shortcuts importrenderfrom rest_framework.viewsets importViewSetfrom students.models importStudentfrom collect.serializers importStudentModelSerializerfrom rest_framework.response importResponse#Create your views here.

classStudent1ViewSet(ViewSet):defget_5(self,request):#取出所有,并切片操作

queryset = Student.objects.all()[:5]#实例化

serializer = StudentModelSerializer(instance=queryset,many=True)returnResponse(serializer.data)defget_5_female(self,request):

queryset= Student.objects.filter(sex=False)[:5]

serializer= StudentModelSerializer(instance=queryset, many=True)returnResponse(serializer.data)defget_one(self,request,pk):

student_obj= Student.objects.get(pk=pk)

serializer= StudentModelSerializer(instance=student_obj)returnResponse(serializer.data)from rest_framework.viewsets importGenericViewSetclassStudent3GenericViewSet(GenericViewSet):

serializer_class=StudentModelSerializer

queryset=Student.objects.all()defget_5(self, request):

student_list= self.get_queryset()[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)defget_5_female(self, request):

student_list= self.get_queryset().filter(sex=False)[:5]

serializer= self.get_serializer(instance=student_list, many=True)returnResponse(serializer.data)from rest_framework.mixins importListModelMixin, CreateModelMixinclassStudent4GenericViewSet(GenericViewSet, ListModelMixin, CreateModelMixin):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importModelViewSetclassStudent5ModelViewSet(ModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.viewsets importReadOnlyModelViewSetclassStudent6ReadOnlyModelViewSet(ReadOnlyModelViewSet):

queryset=Student.objects.all()

serializer_class=StudentModelSerializerfrom rest_framework.decorators importactionclassStudent7ModelViewSet(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)defget_5(self, request, pk):

serilizer= self.get_serializer(instance=self.get_queryset().get(pk=pk))returnResponse(serilizer.data)from rest_framework.generics importGenericAPIViewfrom collect.serializers importStudentInfoModelSerializerclassStudent8GenericAPIView(GenericAPIView):

queryset=Student.objects.all()#GenericAPI内部调用序列化器的方法,我们可以重写这个方法来实现根据不同的需求来调用不同的序列化器

defget_serializer_class(self):if self.request.method == "GET":#2个字段

returnStudentInfoModelSerializerreturnStudentModelSerializerdefget(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)

returnResponse(serializer.data)defpost(self, request):"""添加数据"""data=request.data

serializer= self.get_serializer(data=data)

serializer.is_valid(raise_exception=True)

serializer.save()returnResponse(serializer.data)classStudent9ModelViewSet(ModelViewSet):

queryset=Student.objects.all()defget_serializer_class(self):#本次客户端请求的视图方法名 self.action

print(self.action)if self.action == "list":returnStudentInfoModelSerializerreturn StudentModelSerializer

get获取所有,只返回两个字段

17ed6362b9ec06be245ad612b7814f0d.png

打印的结果是list

06109dd00928b23711d2ae05ef05c0ea.png

输出单个信息,会输出4个字段

655bed3499f3337c34971b40295aa22a.png

方法名称

fdd69495becf52e374886caa9bb43fa8.png

三  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 importadminfrom django.urls importpath,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 importpathfrom opt importviews

urlpatterns=[

path('auth1/', views.Demo1APIView.as_view()),

path('auth2/', views.Demo2APIView.as_view()),]

views文件

from django.shortcuts importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")

0d5af8e81999cf3f759d82bad3d6cd1c.png

创建一个admin用户进行管理

4407f53b2666f6004718838e414546a4.png

e4dfbc71375106ae191f3f7b623d84b5.png

10ad4f7dd049da149c9b1164663737b0.png

2d073bc68f9fc04a12d02958ceacd54e.png

创建一个alex用户

使用alex登录,同时取消人员状态

1a7da07f6d5b2a44cdc29d4ab639c708.png

013aeb30360dc15b5135e83401b4e968.png

必须是一个超级管理员用户才能看见

查看数据的seeeion

mysql> select * from django_session;

+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+

| session_key | session_data | expire_date |

+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+

| fn55zqveedvfjckalewwusqny7iadhun | MWM5NDBiNmI0ZDZlYTFmZmM4MjE4YTkyODcyMWNmNTQ4NjJkNDJkNTp7Il9hdXRoX3VzZXJfaWQiOiIyIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiIwMTY2ZDUxMTFhYzU2ZTBjMWRkZDU5ZmM3MmE5ZmI1ZjcyYWY4NmMxIn0= | 2020-05-05 07:27:10.353593 |

+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+

3.2 权限Permissions控制

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

在执行视图的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 importpath,re_pathfrom opt importviews

urlpatterns=[

path('auth1/', views.Demo1APIView.as_view()),

path('auth2/', views.Demo2APIView.as_view()),#自定义权限

path('auth3/', views.Demo3APIView.as_view()),

]

views配置

from django.shortcuts importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")#自定义权限

from rest_framework.permissions importBasePermissionclassMyPermission(BasePermission):defhas_permission(self, request, view):"""针对访问视图进行权限判断

:param request: 本次操作的http请求对象

:param view: 本次访问路由对应的视图对象

:return:"""

if request.user.username == "xiaoming":returnTruereturnFalseclassDemo3APIView(APIView):

permission_classes=[MyPermission]defget(self, request):"""个人中心3"""

return Response("个人中心3")

创建xiaoming用户

(drfdemo) root@darren-virtual-machine:~/PycharmProjects/drfdemo/drf_demo# python3 manage.py createsuperuser

使用root登录访问auth3

74c39c3dcab4e54c2b67e05bf0b7eb6c.png

使用ixaoming用户登录访问

a68424e70e82aaee64928eb3b5dc126d.png

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 importpath,re_pathfrom opt importviews

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 importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")#自定义权限

from rest_framework.permissions importBasePermissionclassMyPermission(BasePermission):defhas_permission(self, request, view):"""针对访问视图进行权限判断,必须使用xiaoming用户

:param request: 本次操作的http请求对象

:param view: 本次访问路由对应的视图对象

:return:"""

if request.user.username == "xiaoming":returnTruereturnFalseclassDemo3APIView(APIView):

permission_classes=[MyPermission]defget(self, request):"""个人中心3"""

return Response("个人中心3")#限流

from rest_framework.throttling importUserRateThrottle, AnonRateThrottleclassDemo4APIView(APIView):

throttle_classes= [UserRateThrottle, AnonRateThrottle] #全局配置后,这里就不用指定

defget(self, request):"""投票页面"""

return Response("投票页面")

访问auth4

907ce82f4d9e8cbdf2cb3a924b6887e1.png

当超过3次

b7295e2f655e72d7c0d5f57257295b3b.png

注销用户,使用匿名用户次数超标

8e92fde451d82bbc463cb6ff0c7f8762.png

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 importpath,re_pathfrom opt importviews

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 importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")#自定义权限

from rest_framework.permissions importBasePermissionclassMyPermission(BasePermission):defhas_permission(self, request, view):"""针对访问视图进行权限判断,必须使用xiaoming用户

:param request: 本次操作的http请求对象

:param view: 本次访问路由对应的视图对象

:return:"""

if request.user.username == "xiaoming":returnTruereturnFalseclassDemo3APIView(APIView):

permission_classes=[MyPermission]defget(self, request):"""个人中心3"""

return Response("个人中心3")#限流

from rest_framework.throttling importUserRateThrottle, AnonRateThrottleclassDemo4APIView(APIView):

throttle_classes= [UserRateThrottle, AnonRateThrottle] #全局配置后,这里就不用指定

defget(self, request):"""投票页面"""

return Response("投票页面")#过滤

from rest_framework.generics importGenericAPIView, ListAPIViewfrom students.models importStudentfrom opt.serializers importStudentModelSerializerfrom django_filters.rest_framework importDjangoFilterBackend#'django_filters.rest_framework.DjangoFilterBackend'

classDemo5APIView(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',)

}

3dc9b0689f709f5dff3190d4768a7d9a.png

点击过滤器

35ff19f9930ca61cf217ebe16148ed6b.png

提交

45280eace9d5b2271bbba34317ccb4b9.png

3.5 排序Ordering

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

使用方法:

在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

路由配置

from django.urls importpath,re_pathfrom opt importviews

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 importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")#自定义权限

from rest_framework.permissions importBasePermissionclassMyPermission(BasePermission):defhas_permission(self, request, view):"""针对访问视图进行权限判断,必须使用xiaoming用户

:param request: 本次操作的http请求对象

:param view: 本次访问路由对应的视图对象

:return:"""

if request.user.username == "xiaoming":returnTruereturnFalseclassDemo3APIView(APIView):

permission_classes=[MyPermission]defget(self, request):"""个人中心3"""

return Response("个人中心3")#限流

from rest_framework.throttling importUserRateThrottle, AnonRateThrottleclassDemo4APIView(APIView):

throttle_classes= [UserRateThrottle, AnonRateThrottle] #全局配置后,这里就不用指定

defget(self, request):"""投票页面"""

return Response("投票页面")#过滤

from rest_framework.generics importGenericAPIView, ListAPIViewfrom students.models importStudentfrom opt.serializers importStudentModelSerializerfrom django_filters.rest_framework importDjangoFilterBackend#'django_filters.rest_framework.DjangoFilterBackend'

classDemo5APIView(ListAPIView):

queryset=Student.objects.all()

serializer_class=StudentModelSerializer

filter_backends= [DjangoFilterBackend] #全局配置后,这里就不用指定了。

filter_fields = ['age', "id"] #声明过滤字段

#排序

from rest_framework.filters importOrderingFilterclassDemo6APIView(ListAPIView):

queryset=Student.objects.all()

serializer_class=StudentModelSerializer

filter_backends= [DjangoFilterBackend, OrderingFilter] #局部配置会覆盖全局配置

filter_fields = ['id', "sex"]

ordering_fields= ['id', "age"]

5bd863c9b4ba75bceb92fd592a6f3dd5.png

点击过滤器

6cacf2d0a77f39568c0b775c39bd0f86.png

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 importpath,re_pathfrom opt importviews

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 importrender#Create your views here.

from rest_framework.views importAPIViewfrom rest_framework.response importResponsefrom rest_framework.permissions importIsAuthenticated, IsAdminUser#用户的认证和权限识别

classDemo1APIView(APIView):#只允许登录后的用户访问

permission_classes =[IsAuthenticated]defget(self, request):#个人中心

return Response("个人中心")classDemo2APIView(APIView):#只允许管理员访问

permission_classes =[IsAdminUser]defget(self, request):#个人中心2

return Response("个人中心2")#自定义权限

from rest_framework.permissions importBasePermissionclassMyPermission(BasePermission):defhas_permission(self, request, view):"""针对访问视图进行权限判断,必须使用xiaoming用户

:param request: 本次操作的http请求对象

:param view: 本次访问路由对应的视图对象

:return:"""

if request.user.username == "xiaoming":returnTruereturnFalseclassDemo3APIView(APIView):

permission_classes=[MyPermission]defget(self, request):"""个人中心3"""

return Response("个人中心3")#限流

from rest_framework.throttling importUserRateThrottle, AnonRateThrottleclassDemo4APIView(APIView):

throttle_classes= [UserRateThrottle, AnonRateThrottle] #全局配置后,这里就不用指定

defget(self, request):"""投票页面"""

return Response("投票页面")#过滤

from rest_framework.generics importGenericAPIView, ListAPIViewfrom students.models importStudentfrom opt.serializers importStudentModelSerializerfrom django_filters.rest_framework importDjangoFilterBackend#'django_filters.rest_framework.DjangoFilterBackend'

classDemo5APIView(ListAPIView):

queryset=Student.objects.all()

serializer_class=StudentModelSerializer

filter_backends= [DjangoFilterBackend] #全局配置后,这里就不用指定了。

filter_fields = ['age', "id"] #声明过滤字段

#排序

from rest_framework.filters importOrderingFilterclassDemo6APIView(ListAPIView):

queryset=Student.objects.all()

serializer_class=StudentModelSerializer

filter_backends= [DjangoFilterBackend, OrderingFilter] #局部配置会覆盖全局配置

filter_fields = ['id', "sex"]

ordering_fields= ['id', "age"]#分页

from rest_framework.pagination importPageNumberPagination, LimitOffsetPagination"""1. 自定义分页器,定制分页的相关配置"""

"""# 页码分页 PageNumberPagination

前端访问形式:GET http://127.0.0.1:8000/opt/data7/?page=4

page=1 limit 0,10

page=2 limit 10,20

# 偏移量分页 LimitOffsetPagination

前端访问形式:GET http://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"""

classStandardPageNumberPagination(PageNumberPagination):"""分页相关配置"""page_query_param= "page" #设置分页页码关键字名

page_size = 3 #设置每页显示数据条数

page_size_query_param = "size" #设置指定每页大小的关键字名

max_page_size = 5 #设置每页显示最大值

classStandardLimitOffsetPagination(LimitOffsetPagination):

default_limit= 2 #默认限制,默认值与PAGE_SIZE设置一致

limit_query_param = "size" #limit参数名

offset_query_param = "start" #offset参数名

max_limit = 5 #最大limit限制

classDemo7APIView(ListAPIView):

queryset=Student.objects.all()

serializer_class=StudentModelSerializer#分页

#页码分页类

pagination_class =StandardPageNumberPagination#偏移量分页类

#pagination_class = StandardLimitOffsetPagination

e52060de26f94f223d50cb48edee1471.png

ce643313043c8dbd755ff64870e4a0a1.png

但是只显示五个,是在代码设置最大显示5个,当设置显示8个时,不会生效,只会显示5个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值