不做大哥好多年 不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核

逍遥子

不做大哥好多年
首页
  • MySQL
  • Redis
  • Elasticsearch
  • Kafka
  • Etcd
  • MongoDB
  • TiDB
  • RabbitMQ
  • 01.GO基础
  • 02.面向对象
  • 03.并发编程
  • 04.常用库
  • 05.数据库操作
  • 06.Beego框架
  • 07.Beego商城
  • 08.GIN框架
  • 09.GIN论坛
  • 10.微服务
  • 01.Python基础
  • 02.Python模块
  • 03.Django
  • 04.Flask
  • 05.SYL
  • 06.Celery
  • 10.微服务
  • 01.Java基础
  • 02.面向对象
  • 03.Java进阶
  • 04.Web基础
  • 05.Spring框架
  • 100.微服务
  • Docker
  • K8S
  • 容器原理
  • Istio
  • 数据结构
  • 算法基础
  • 算法题分类
  • 前置知识
  • PyTorch
  • 01.Python
  • 02.GO
  • 03.Java
  • 04.业务问题
  • 05.关键技术
  • 06.项目常识
  • 10.计算机基础
  • Linux基础
  • Linux高级
  • Nginx
  • KeepAlive
  • ansible
  • zabbix
  • Shell
  • Linux内核
  • python基础

  • python模块

  • django

    • 01_Django基础

    • 02_Model数据库操作

    • 03_DRF框架

      • 01.web开发两种模式
      • 02.Restful风格
      • 03.DRF框架作用
      • 04.环境安装与使用
      • 05.Serializer
      • 06.ModelSerializer
      • 07.APIView
        • 01.APIView介绍
          • 1.1 APIView特点
          • 1.2 Request对象
          • 1.3 Response对象
        • 02.DRF全局配置
          • 2.1 settings.py注册
          • 2.2 全局配置DRF
        • 03.APIView基本使用
          • 3.1 book/models.py
          • 3.2 book/serializers.py
          • 3.3 book/views.py
          • 3.4 book/urls.py
          • 3.5 测试接口
          • 3.5.1 get获取数据
          • 3.5.2 post添加数据
          • 3.5.3 put修改数据
        • 04.自定义分页
          • 4.1 自定义分页
          • 4.2 测试分页效果
        • 05.认证权限
          • 5.1 使用自带权限
          • 5.2 自定义权限
          • 5.2.1 自定义权限
          • 5.2.2 使用自定义权限
        • 06.限流
          • 6.1 全局配置
          • 6.2 指定视图配置
        • 07.过滤
          • 7.1 自定义过滤
          • 7.2 测试过滤功能
        • 08.排序
          • 8.1 配置排序
          • 8.2 测试排序功能
      • 08.初始化项目结构
      • 09.ModelViewSet
    • 04_部署

  • flask

  • SYL

  • Celery

  • 微服务

  • python
  • django
  • 03_DRF框架
xiaonaiqiang
2021-02-17
目录

07.APIView

# 01.APIView介绍

# 1.1 APIView特点

APIView是REST framework提供的所有视图的基类,继承自Django的View类。

APIView与View的区别:

  • 请求对象:传入到视图中的request对象是REST framework的Request对象,而不再是Django原始的HttpRequest对象;
  • 响应对象:视图可以直接返回REST framework的Response对象,响应数据会根据客户端请求头Accpet自动转换为对应的格式进行返回;
  • 异常处理:任何APIException的子异常都会被DRF框架默认的异常处理机制处理成对应的响应信息返回给客户端;
  • 其他功能:认证、权限、限流。

# 1.2 Request对象

  • 视图继承APIView之后,传入视图的request对象是DRF框架提供的Request类的对象
  • Request类的对象有两个属性:
属性名 说明
data 包含解析之后的请求体数据,已经解析为了字典或类字典,相当于Django原始request对象的body、POST、FILES属性。
query_params 包含解析之后的查询字符串数据,相当于Django原始request对象的GET属性

# 1.3 Response对象

  • 视图继承APIView之后,响应时可以统一返回Response对象,格式如下:
from rest_framework.response import Response

response = Response(<原始响应数据>)
1
2
3
  • 原始的响应数据,会根据客户端请求头的Accpet,自动转换为对应的格式并进行返回,如:
Accept请求头 说明
application/json 服务器会将原始响应数据转换为json数据进行返回,没指定Accept时,默认返回json
text/html 服务器会将原始响应数据转换为html网页进行返回

# 02.DRF全局配置

# 2.1 settings.py注册

  • 注册
INSTALLED_APPS = [
    'rest_framework',
    'django_filters',
]
1
2
3
4

# 2.2 全局配置DRF

# 过滤器
# 1,安装 django-filter
# 2,注册应用
# 3,配置settings, 在view里配置可过滤的字段
# 4,使用 查询字符串携带过滤信息

REST_FRAMEWORK = {
    # 1.认证器(全局):用户登录校验用户名密码或者token是否合法
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', # 在DRF中配置JWT认证
        'rest_framework.authentication.SessionAuthentication',          # 使用session时的认证器
        'rest_framework.authentication.BasicAuthentication'             # 提交表单时的认证器
    ],
    #2.权限配置(全局): 顺序靠上的严格(根据不同的用户角色,可以操作不同的表)
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.IsAdminUser',                # 管理员可以访问
        # 'rest_framework.permissions.IsAuthenticated',            # 认证用户可以访问
        # 'rest_framework.permissions.IsAuthenticatedOrReadOnly',  # 认证用户可以访问, 否则只能读取
        # 'rest_framework.permissions.AllowAny',                   # 所有用户都可以访问
    ],
    #3.限流(防爬虫)
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle',
    ],
    #3.1限流策略
    'DEFAULT_THROTTLE_RATES': {
        'user': '1000/hour',    # 认证用户每小时100次
        'anon': '300/day',       # 未认证用户每天能访问3次
    },

    'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
    'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata',
    'DEFAULT_VERSIONING_CLASS': None,

    #4.分页(全局):全局分页器, 例如 省市区的数据自定义分页器, 不需要分页
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    # 每页返回数量
    'PAGE_SIZE': 10,  # 默认 None

    #5.过滤器后端
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        # 'django_filters.rest_framework.backends.DjangoFilterBackend', 包路径有变化
    ],

    #5.1过滤排序(全局):Filtering 过滤排序
    'SEARCH_PARAM': 'search',
    'ORDERING_PARAM': 'ordering',

    'NUM_PROXIES': None,

    #6.版本控制:Versioning  接口版本控制
    'DEFAULT_VERSION': None,
    'ALLOWED_VERSIONS': None,
    'VERSION_PARAM': 'version',
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 03.APIView基本使用

# 3.1 book/models.py

from django.db import models

#定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    bpub_date = models.DateField(verbose_name='发布日期')
    bread = models.IntegerField(default=0, verbose_name='阅读量')
    bcomment = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'tb_books'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称
        verbose_name_plural = verbose_name  # 显示的复数名称

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.btitle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.2 book/serializers.py

# -*- coding: utf-8 -*-
from rest_framework import serializers
from book.models import BookInfo

class BookInfoSerializer2(serializers.ModelSerializer):
    """图书序列化器类"""
    class Meta:
        model = BookInfo
        fields = '__all__'
1
2
3
4
5
6
7
8
9

# 3.3 book/views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from book import serializers
from book.models import BookInfo

class APIViewBookInfoViewSet(APIView):
    def get(self, request):
        obj = BookInfo.objects.all()
        ser = serializers.BookInfoSerializer2(instance=obj, many=True)  # 关联数据多条
        return Response(ser.data)
1
2
3
4
5
6
7
8
9
10

# 3.4 book/urls.py

from django.urls import re_path,path
from book import views

urlpatterns = [
    path('book1/', views.APIViewBookInfoViewSet.as_view()),
]
1
2
3
4
5
6

# 3.5 测试接口

# 3.5.1 get获取数据

http://127.0.0.1:8000/book/book1/

[
    {
        "id": 1,
        "btitle": "西游记",
        "bpub_date": "2020-08-11",
        "bread": 666,
        "bcomment": 123,
        "heroinfo_set": [],
        "xxx": "西游记"
    },
    {
        "id": 2,
        "btitle": "水浒传",
        "bpub_date": "2020-08-11",
        "bread": 200,
        "bcomment": 100,
        "heroinfo_set": [],
        "xxx": "水浒传"
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 3.5.2 post添加数据

http://127.0.0.1:8000/book/book1/

# 3.5.3 put修改数据

http://127.0.0.1:8000/book/book1/?pk=4

# 04.自定义分页

# 4.1 自定义分页

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from book import serializers
from book.models import BookInfo


# 分页(局部):自定义分页器 局部
class PageNum(PageNumberPagination):
    # 查询字符串中代表每页返回数据数量的参数名, 默认值: None
    page_size_query_param = 'page_size'
    # 查询字符串中代表页码的参数名, 有默认值: page
    # page_query_param = 'page'
    # 一页中最多的结果条数
    max_page_size = 2

class APIViewBookInfoViewSet(APIView):
    def get(self, request):
        queryset = BookInfo.objects.all()
        # 分页
        pg = PageNum()
        page_objs = pg.paginate_queryset(queryset=queryset, request=request, view=self)
        ser = serializers.BookInfoSerializer2(instance=page_objs, many=True)  # 关联数据多条
        return Response(ser.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 4.2 测试分页效果

查找第一页,每页显示两条数据

http://127.0.0.1:8000/book/book1/?page=1&page_size=2

# 05.认证权限

# 5.1 使用自带权限

# 注:认证类都在 `rest_framework.authentication` 模块中
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny


class APIViewBookInfoViewSet(APIView):
    authentication_classes = (SessionAuthentication,)
    # permission_classes = [IsAuthenticated]   # 只有认证用户才能访问接口
    permission_classes = [AllowAny]   # 只有认证用户才能访问接口

    def get(self, request):
        queryset = BookInfo.objects.all()
        # 分页
        pg = PageNum()
        page_objs = pg.paginate_queryset(queryset=queryset, request=request, view=self)
        ser = serializers.BookInfoSerializer2(instance=page_objs, many=True)  # 关联数据多条
        return Response(ser.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 5.2 自定义权限

# 5.2.1 自定义权限

from rest_framework.permissions import BasePermission

# 自定义权限(局部)
class MyPermission(BasePermission):
    # has_permission 是用户对这个视图有没有 GET POST PUT PATCH DELETE 权限的分别判断
    def has_permission(self, request, view):
        print('has_perm')
        # print(view.kwargs.get("pk"), request.user.id)
        """判断用户对模型有没有访问权"""
        # 任何用户对使用此权限类的视图都有访问权限
        if request.user.is_superuser:
            # 管理员对用户模型有访问权
            return True
        elif view.kwargs.get('pk') == str(request.user.id):
            # 携带的id和用户的id相同时有访问权
            return True
        return False

    # has_object_permission 是用户过了 has_permission 判断有权限以后,再判断这个用户有没有对一个具体的对象有没有操作权限
    def has_object_permission(self, request, view, obj):
        print('has_object_perm')
        """获取单个数据时,判断用户对某个数据对象是否有访问权限"""
        if request.user.id == obj.id:
            return True
        return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 5.2.2 使用自定义权限

# 注:认证类都在 `rest_framework.authentication` 模块中
from rest_framework.authentication import SessionAuthentication

class APIViewBookInfoViewSet(APIView):
    authentication_classes = (SessionAuthentication,)
    permission_classes = [MyPermission,]     # 只有认证用户才能访问接口

    def get(self, request):
        queryset = BookInfo.objects.all()
        # 分页
        pg = PageNum()
        page_objs = pg.paginate_queryset(queryset=queryset, request=request, view=self)
        ser = serializers.BookInfoSerializer2(instance=page_objs, many=True)  # 关联数据多条
        return Response(ser.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 06.限流

# 6.1 全局配置

  • DEFAULT_THROTTLE_RATES 可以使用 second、minute、hour 或day来指明限流周期。
REST_FRAMEWORK = {
    ...
    # 针对匿名用户和认证通过用户分别进行限流控制
    'DEFAULT_THROTTLE_CLASSES': (
        # 针对未登录(匿名)用户的限流控制类
        'rest_framework.throttling.AnonRateThrottle',
        # 针对登录(认证通过)用户的限流控制类
        'rest_framework.throttling.UserRateThrottle'
    ),
    # 指定限流频次
    'DEFAULT_THROTTLE_RATES': {
        # 认证用户的限流频次
        'user': '5/minute',
        # 匿名用户的限流频次
        'anon': '3/minute',
    },
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 6.2 指定视图配置

  • 也可以某个视图中通过 throttle_classes 属性来指定某视图所使用的限流控制类
from rest_framework.throttling import AnonRateThrottle

class BookInfoViewSet(ReadOnlyModelViewSet):
    ...
    # 此时设置当前视图仅针对匿名用户进行限流控制
    throttle_classes = [AnonRateThrottle]
1
2
3
4
5
6

# 07.过滤

# 7.1 自定义过滤

from django_filters.rest_framework import DjangoFilterBackend

class APIViewBookInfoViewSet(APIView):
    filter_backends = (DjangoFilterBackend,)
    # 指定过滤字段, 不设置, 过滤功能不起效
    filter_fields = ('btitle', )  # ?username=tom&phone=&is_active=true

    def filter_queryset(self, queryset):
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset

    def get(self, request):
        queryset = BookInfo.objects.all()
        # 过滤
        queryset = self.filter_queryset(queryset)

        # 分页
        pg = PageNum()
        page_objs = pg.paginate_queryset(queryset=queryset, request=request, view=self)
        ser = serializers.BookInfoSerializer2(instance=page_objs, many=True)  # 关联数据多条
        return Response(ser.data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 7.2 测试过滤功能

http://127.0.0.1:8000/book/book1/?btitle=西游记

# 08.排序

# 8.1 配置排序

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter

class APIViewBookInfoViewSet(APIView):
    filter_backends = (DjangoFilterBackend,OrderingFilter)
    # 指定过滤字段, 不设置, 过滤功能不起效
    filter_fields = ('btitle', )  # ?username=tom&phone=&is_active=true
    # 5.1指定排序字段, 不设置, 排序功能不起效
    ordering_fields = ('id',)    # ?ordering=-id

    def filter_queryset(self, queryset):
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 8.2 测试排序功能

http://127.0.0.1:8000/book/book1/?ordering=-id

上次更新: 2024/3/13 15:35:10
06.ModelSerializer
08.初始化项目结构

← 06.ModelSerializer 08.初始化项目结构→

最近更新
01
04.数组双指针排序_子数组
03-25
02
08.动态规划
03-25
03
06.回溯算法
03-25
更多文章>
Theme by Vdoing | Copyright © 2019-2025 逍遥子 技术博客 京ICP备2021005373号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式