刘沙河 刘沙河
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希

花开半夏,半夏花开
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希
  • Python基础

  • Python进阶

  • Python并发编程

  • Django

    • django 常见命令
    • Django模板母版
    • Django视图
    • Django路由系统
    • Django--orm系统-指令&属性
    • Django--orm系统 -分组聚合
    • Django-cookie&session
    • middleware中间件
    • Django 的身份认证系统
    • Django models 之字段详解
    • Django缓存系统
    • Django数据库系统
    • Django信号系统
    • Django序列化和反序列化
    • Django中admin用法
    • DRF 版本、认证、权限、限制、解析器和渲染器
    • DRF(Django REST Framework)框架
      • 一.DRF中的Request
      • 二.前戏: 关于面向对象的继承
      • 三.初级版本
        • 1. settings.py文件 -- 注册app
        • 2. models.py文件 -- 创建表
        • 3. admin.py文件
        • 4. 根目录下urls.py -- 路由匹配
        • 5. bms/views.py -- 视图函数
        • 6. bms/modelserializers.py -- 自定义序列化工具
      • 四.进化版: 使用自定义混合类和自定义通用类
      • 五.超级进化版: 使用GenericViewSet通用类
      • 六.究极进化版: 使用rest_framework帮我们封装好的通用类和混合类
      • 七.终极进化版: 使用rest_framework帮我们封装好的路由DefaultRouter
  • Flask

  • 爬虫

  • Python
  • Django
bigox
2021-03-22
目录

DRF(Django REST Framework)框架

# 一.DRF中的Request

在Django REST Framework中内置的Request类扩展了Django中的Request类, 实现了很多方便的功能 -- 如请求数据解析和认证等.

比如, 区别于Django中的request: 从request.GET中获取URL参数, 从request.POST中去取某些情况下的POST数据(前端提交过来的数据).

在APIView中封装的request, 就实现了请求数据的解析:

  • 对于GET请求的参数, APIView通过request.query_params来获取
  • 对于POST请求、PUT请求的数据, APIView通过request.data来获取

# 二.前戏: 关于面向对象的继承

# 讲一个葫芦娃的故事

class Wa1(object):
    name = "红娃"

    def f1(self):
        print("力大无穷!")


class Wa2(object):
    name = '橙娃'

    def f2(self):
        print('千里眼顺风耳!')


class Wa3(object):
    name = '黄娃'

    def f3(self):
        print('钢筋铁骨!')


class Wa4(object):
    name = '绿娃'

    def f4(self):
        print("会喷火!")


class Wa5(object):
    name = '青蛙'

    def f5(self):
        print("会喷水!")


class Jishuwa(Wa1, Wa3, Wa5):
    name = '奇数娃'

    def ff(self):
        print("我是{}, 我会:".format(self.name))
        self.f1()
        self.f3()
        self.f5()


class Oushuwa(Wa2, Wa4):
    name = '偶数娃'

    def ff(self):
        print("我是{}, 我会:".format(self.name))
        self.f2()
        self.f4()


jsw = Jishuwa()
jsw.ff()
osw = Oushuwa()
osw.ff()


# 直接定义一个基数娃
class Taowa(Wa1, Wa3, Wa5):
    name = '套娃'

    def ff(self):
        print("我是{}, 我会:".format(self.name))
        self.f1()
        self.f3()
        self.f5()


class Wawa(Taowa):
    pass


print("=" * 120)
a = Wawa()
a.ff()
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

# 三.初级版本

# 1. settings.py文件 -- 注册app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bms.apps.BmsConfig',
    'rest_framework',   # 注册app
]
1
2
3
4
5
6
7
8
9
10

# 2. models.py文件 -- 创建表

from django.db import models

# 出版社表
class Publisher(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name

# 书籍表
class Book(models.Model):
    title = models.CharField(max_length=32)
    publisher = models.ForeignKey(to='Publisher', to_field='id', on_delete=models.CASCADE)

    def __str__(self):
        return self.title
# cd到当前项目目录
# 执行数据库迁移指令
python manage.py makemigrations
python manage.py migrate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 3. admin.py文件

from django.contrib import admin
from bms import models  # bms是我们的app

admin.site.register(models.Publisher)
admin.site.register(models.Book)
# 创建超级用户
# cd到当前项目目录
python manage.py createsuperuser
# 启动Django项目
python manage.py runserver 127.0.0.1:8000
# 浏览器地址栏输入 127.0.0.1:8000
# 输入账号和密码,进入admin页面,对数据库中的表 添加或修改相关数据
1
2
3
4
5
6
7
8
9
10
11
12

# 4. 根目录下urls.py -- 路由匹配

from django.conf.urls import url
from django.contrib import admin
from bms import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    url(r'^book/$', views.BookListView.as_view()),
    url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
]
1
2
3
4
5
6
7
8
9
10

# 5. bms/views.py -- 视图函数

from rest_framework.response import Response
from rest_framework.views import APIView
from bms import models
from bms.modelserializers import BookModelSerializer


class BookListView(APIView):
    def get(self, request):
        # 1.从数据库查询出所有书籍对象
        queryset = models.Book.objects.all()
        # 2.使用modelserializer对获取的对象进行序列化
        ser_obj = BookModelSerializer(queryset, many=True)
        return Response(ser_obj.data)

    def post(self, request):
        # 1.获取前端提交过来的数据 --> request.data
        # 2.对数据进行有效性校验
        ser_obj = BookModelSerializer(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('添加成功!')
        else:
            return Response(ser_obj.errors)


class BookDetailView(APIView):
    def get(self, request, pk):  # get获取具体某本书的信息
        # 1.根据pk去数据库中查询具体的那本书籍对象
        book_obj = models.Book.objects.filter(pk=pk).first()
        if book_obj:
            # 2.将书籍对象 序列化成 json格式的数据
            ser_obj = BookModelSerializer(book_obj)
            # 3.返回响应
            return Response(ser_obj.data)
        else:
            return Response('无效的书籍id')

    def put(self, request, pk):  # put修改具体某本书的信息
        # 1.根据pk去查询具体的那本书籍对象
        book_obj = models.Book.objects.filter(pk=pk).first()
        if book_obj:
            # 2.获取用户发送过来的数据并修改数据
            ser_obj = BookModelSerializer(instance=book_obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                # 3.保存并返回修改后的数据
                ser_obj.save()
                return Response(ser_obj.data)
            else:
                return Response(ser_obj.errors)
        else:
            return Response('无效的书籍id')

    def delete(self, request, pk):  # delete删除具体某一本书籍对象
        # 1.根据pk去查询具体的那本书籍对象
        book_obj = models.Book.objects.filter(pk=pk).first()
        if book_obj:
            # 2.删除该书籍对象
            book_obj.delete()
            return Response('删除成功')
        else:
            return Response('无效的书籍id')
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
58
59
60
61

# 6. bms/modelserializers.py -- 自定义序列化工具

from rest_framework import serializers
from bms import models


class PublisherSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField()


class BookModelSerializer(serializers.ModelSerializer):
    publisher_info = serializers.SerializerMethodField(read_only=True)

    def get_publisher_info(self, book_obj):
        return PublisherSerializer(book_obj.publisher).data

    class Meta:
        model = models.Book
        fields = '__all__'
        extra_kwargs = {
            'publisher': {'write_only': True},
        }


class PublisherModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Publisher
        fields = '__all__'
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

# 四.进化版: 使用自定义混合类和自定义通用类

提取出views.py文件中函数BookListView和BookDetailView代码中的重复部分, 并将这些重复部分封装为通用类(Generic)和混合类(Mixin), 利用Python强大的多继承功能, 将代码进一步优化. 充分体现Python语言的"优雅"和"简洁".

注意: 混合类Mixin不能单独实例化, 需要与其他的类搭配使用.

bms/views.py:

from rest_framework.response import Response
from rest_framework.views import APIView
from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer


# 通用功能
class GenericView(APIView):
    queryset = None
    serializer_class = None

    def get_queryset(self, request, *args, **kwargs):
        # 再一次调用all()方法: 让每次请求来的时候都重新查一次数据
        return self.queryset.all()

    def get_obj(self, request, pk, *args, **kwargs):
        return self.get_queryset(request, *args, **kwargs).filter(pk=pk).first()


# get展示(全部)资源
class ListMixin(object):
    def get(self, request):
        queryset = self.get_queryset(request)
        ser_obj = self.serializer_class(queryset, many=True)
        return Response(ser_obj.data)


# post添加资源
class CreateMixin(object):
    def post(self, request):
        ser_obj = self.serializer_class(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('添加成功!')
        else:
            return Response(ser_obj.errors)


# get展示(部分)资源
class RetrieveMixin(object):
    def get(self, request, pk, *args, **kwargs):
        obj = self.get_obj(request, pk, *args, **kwargs)
        if obj:
            ser_obj = self.serializer_class(obj)
            return Response(ser_obj.data)
        else:
            return Response('无效的id!')


# put更新(修改)资源
class UpdateMixin(object):
    def put(self, request, pk, *args, **kwargs):
        obj = self.get_obj(request, pk, *args, **kwargs)
        if obj:
            ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.data)
            else:
                return Response(ser_obj.errors)
        else:
            return Response('无效的id!')


# delete删除资源
class DestroyMixin(object):
    def delete(self, request, pk, *args, **kwargs):
        obj = self.get_obj(request, pk, *args, **kwargs)
        if obj:
            obj.delete()
            return Response('删除成功!')
        else:
            return Response('无效的id!')


class BookListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer


class BookDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer


class PublisherListView(GenericView, ListMixin, CreateMixin):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer


class PublisherDetailView(GenericView, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

urls.py:

from django.conf.urls import url
from django.contrib import admin
from bms import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    url(r'^book/$', views.BookListView.as_view()),
    url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view()),
    url(r'^publisher/$', views.PublisherListView.as_view()),
    url(r'^publisher/(?P<pk>\d+)$', views.PublisherDetailView.as_view()),
]
1
2
3
4
5
6
7
8
9
10
11
12

# 五.超级进化版: 使用GenericViewSet通用类

GenericViewSet是rest_framework这个app中已经封装好了的一个类:

from rest_framework.viewsets import GenericViewSet
1

需要注意的是, 继承了GenericViewSet以后, GenericViewSet这个类已经帮我们封装好了get_queryset()和get_object()这两个方法, 它们不需要接收参数, 我们直接调用即可.

bms/views.py:

from rest_framework.response import Response
from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
from rest_framework.viewsets import GenericViewSet  # 引入GenericViewSet通用类


# get展示(全部)资源
class ListMixin(object):
    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        ser_obj = self.serializer_class(queryset, many=True)
        return Response(ser_obj.data)


# post添加资源
class CreateMixin(object):
    def create(self, request, *args, **kwargs):
        ser_obj = self.serializer_class(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('添加成功!')
        else:
            return Response(ser_obj.errors)


# get展示(部分)资源
class RetrieveMixin(object):
    def retrieve(self, request, pk, *args, **kwargs):
        obj = self.get_object()
        if obj:
            ser_obj = self.serializer_class(obj)
            return Response(ser_obj.data)
        else:
            return Response('无效的id!')


# put更新(修改)资源
class UpdateMixin(object):
    def update(self, request, pk, *args, **kwargs):
        obj = self.get_object()
        if obj:
            ser_obj = self.serializer_class(instance=obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.data)
            else:
                return Response(ser_obj.errors)
        else:
            return Response('无效的id!')


# delete删除资源
class DestroyMixin(object):
    def destroy(self, request, pk, *args, **kwargs):
        obj = self.get_object()
        if obj:
            obj.delete()
            return Response('删除成功!')
        else:
            return Response('无效的id!')


class BookViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer


class PublisherViewSet(GenericViewSet, ListMixin, CreateMixin, RetrieveMixin, UpdateMixin, DestroyMixin):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer
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
58
59
60
61
62
63
64
65
66
67
68
69
70

urls.py:

from django.conf.urls import url
from django.contrib import admin
from bms import views


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    url(r'^book/$', views.BookViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
    url(r'^book/(?P<pk>\d+)$', views.BookViewSet.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
    url(r'^publisher/$', views.PublisherViewSet.as_view(actions={'get': 'list', 'post': 'create'})),
    url(r'^publisher/(?P<pk>\d+)$', views.PublisherViewSet.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]
1
2
3
4
5
6
7
8
9
10
11
12
13

# 六.究极进化版: 使用rest_framework帮我们封装好的通用类和混合类

bms/views.py:

from bms import models
from bms.modelserializers import BookModelSerializer, PublisherModelSerializer
from rest_framework.viewsets import ModelViewSet


class BookViewSet(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer


class PublisherViewSet(ModelViewSet):
    queryset = models.Publisher.objects.all()
    serializer_class = PublisherModelSerializer
1
2
3
4
5
6
7
8
9
10
11
12
13

# 七.终极进化版: 使用rest_framework帮我们封装好的路由DefaultRouter

from rest_framework.routers import DefaultRouter
from bms import views

urlpatterns = []

router = DefaultRouter()
router.register('book', views.BookViewSet)
router.register('publisher', views.PublisherViewSet)

# 重写urlpatterns
urlpatterns += router.urls
1
2
3
4
5
6
7
8
9
10
11
#Python#
上次更新: 2023/04/16, 18:35:33
DRF 版本、认证、权限、限制、解析器和渲染器
Flask基础知识总结&上下文管理

← DRF 版本、认证、权限、限制、解析器和渲染器 Flask基础知识总结&上下文管理→

最近更新
01
go与http代理
05-24
02
自制申威架构k8s-reloader
12-06
03
Docker Buildx 教程
12-01
更多文章>
Theme by Vdoing | Copyright © 2020-2024 小刘扎扎 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式