zoukankan      html  css  js  c++  java
  • 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/ 

  • 相关阅读:
    让外部网络访问K8S service的四种方式
    Kubernetes 针对资源紧缺处理方式的配置
    基于Prometheus,Alermanager实现Kubernetes自动伸缩
    ubuntu16.04下python2、python3环境选择与python升级(pip版本切换)
    学习资源集锦
    tensorflow :ckpt模型转换为pytorch : hdf5模型
    SoftMax多分类器原理及代码理解
    玩转树莓派3
    keras_基本网络层结构(2)_卷积层
    keras_基本网络层结构(1)_常用层
  • 原文地址:https://www.cnblogs.com/zyxnhr/p/12745075.html
Copyright © 2011-2022 走看看