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 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)
访问http://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"})),
]
访问http://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调试,访问http://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"]
访问http://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")
访问http://127.0.0.1:8000/opt/auth1/
创建一个admin用户进行管理
登录http://127.0.0.1:8000/admin/login/?next=/admin/
登陆后,查看http://127.0.0.1:8000/opt/auth1/和 http://127.0.0.1:8000/opt/auth2/
创建一个alex用户
使用alex登录,同时取消人员状态
然后auth1可以正常访问,但是访问http://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 |
+----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+
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 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',)
}
访问http://127.0.0.1:8000/opt/data5/
点击过滤器
提交
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"]
访问http://127.0.0.1:8000/opt/data6/
点击过滤器
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 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
""" 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
访问http://127.0.0.1:8000/opt/data7/
访问http://127.0.0.1:8000/opt/data7/?page=1&size=8,就是每一页显示8个数据
但是只显示五个,是在代码设置最大显示5个,当设置显示8个时,不会生效,只会显示5个
参考:https://www.cnblogs.com/Michael--chen/p/11222143.html,老男孩教育:https://www.oldboyedu.com/
068.Python框架Django之DRF视图集使用的更多相关文章
- 067.Python框架Django之DRF视图类
一 关于视图类的一下概念 drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作.所以在django原有的django.views.View类基础上,drf封装了多个子类出来提供给我们使用. ...
- 使用DRF视图集时自定义action方法
在我们用DRF视图集完成了查找全部部门,创建一个新的部门,查找一个部门,修改一个部门,删除一个部门的功能后,views.py的代码是这样子的: class DepartmentViewSet(Mode ...
- Python学习---django重点之视图函数
django重点之视图函数 http请求中产生两个核心对象: http请求:HttpRequest对象,由Django自己创建 http响应:HttpResponse对象,由开发自己创建,必须返回一个 ...
- DRF视图集的路由设置
在使用DRF视图集时,往往需要配一大堆路由,例如: # views.py class DepartmentViewSet(ListModelMixin,CreateModelMixin,Retriev ...
- python框架Django简介与安装
Django简介 关注公众号"轻松学编程"了解更多. 发布于2005年,最负盛名且成熟的Python网络框架 最初用来制作在线新闻的Web站点 开源Web框架,遵守BSD协议 BS ...
- 对drf视图集的理解
视图集ViewSet 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中: list() 提供一组数据 retrieve() 提供单个数据 create() 创建数据 update() ...
- 编程 - Python - 框架 - Django
一.Django简介 百度百科:一个开放源代码的Web框架,由Python语言编写...... 重点:一个大而全的框架,啥都替你考虑好了. 1. web框架介绍 具体介绍Django之前,必须先介绍W ...
- python框架Django中MTV框架之VIew(业务控制器)
MTV框架之VIew(业务控制器) 关注公众号"轻松学编程"了解更多. 1.什么是视图 视图层=路由表(urls.py)+视图函数(views.py) 其角色相当于MVC中的Con ...
- python框架Django中MTV框架之Template(模板/界面)
MTV框架之Template(模板/界面) 关注公众号"轻松学编程"了解更多. 1.模板目录位置 应用下 不需要注册 无法跨应用地进行复用 工程下 需要注册 settings.py ...
随机推荐
- java 为什么重写equals一定要重写hashcode?
前言 最近复习,又看到了这个问题,在此记录和整理,通过例子来说明这种情况的原因,使大家可以清晰明白这个问题. 初步探索 首先我们要了解equals方法是什么,hashcode方法是什么. equals ...
- 【codeforces】Educational Codeforces Round 80 D. Minimax Problem——二分+二进制处理
题目链接 题目大意 有n个维度为m的向量,取其中两个进行合并,合并时每个维度取两者之间的较大者,得到的新的向量中,维度值最小者最大为多少 分析 首先最需要注意的是m的取值,m最大只有8 那么我们可以二 ...
- java基于Hash表和双向链表简单实现LRU Cache
package lru; import java.util.HashMap; public class LRUCache2<K,V> { public final int capacity ...
- 常见排序算法总结分析之选择排序与归并排序-C#实现
本篇文章对选择排序中的简单选择排序与堆排序,以及常用的归并排序做一个总结分析. 常见排序算法总结分析之交换排序与插入排序-C#实现是排序算法总结系列的首篇文章,包含了一些概念的介绍以及交换排序(冒泡与 ...
- Android对话框(Dialog)
Android对话框 前几天出差没有进行更新,今天写一下安卓中用的比较多的对话框——AlertDialog. dialog就是一个在屏幕上弹出一个可以让用户做出一个选择,或者输入额外的信息的对话框,一 ...
- CF 631C report
Each month Blake gets the report containing main economic indicators of the company "Blake Tech ...
- TensorFlow系列专题(九):常用RNN网络结构及依赖优化问题
欢迎大家关注我们的网站和系列教程:http://panchuang.net/ ,学习更多的机器学习.深度学习的知识! 目录: 常用的循环神经网络结构 多层循环神经网络 双向循环神经网络 递归神经网络 ...
- 报错代码:svn-http status413'requset entity too large
报错代码:svn-http status413'requset entity too large 发现报错,判断问题.解决问题.记录问题. SVN服务器端排查过没有问题,其他客户端都能正常更新.只有一 ...
- 使用FME将CAD中块参照数据转换为shp数据
暴露出需要导出的字段值,首先在数据查看器中看看CAD中各个图层分别有哪些隐含的字段. CAD快参照中含有多个部分,需要将点按照原始编码聚合成一个点. 属性字段创建,并按照属性字段一一对应CAD中的字段 ...
- linux 中的页缓存和文件 IO
本文所述是针对 linux 引入了虚拟内存管理机制以后所涉及的知识点.linux 中页缓存的本质就是对于磁盘中的部分数据在内存中保留一定的副本,使得应用程序能够快速的读取到磁盘中相应的数据,并实现不同 ...