前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >day93-视图封装&路由组件&版本控制

day93-视图封装&路由组件&版本控制

原创
作者头像
少年包青菜
修改2020-03-12 10:16:28
3640
修改2020-03-12 10:16:28
举报
文章被收录于专栏:Python 学习Python 学习

1.视图的第一次封装和第二次封装

1.第一次封装和第二次封装(第二次封装仅仅是整合继承类)

1.1 首先明确封装,因为不同的增删改查的区别就在于 表 不同,序列化器 不同,

表 和 序列化类可以写一个类方法里面

1.2 单条查询和多条查询不一样,分开写

1.3 所以策略是:

-- 先写一个基类,定义空的 queryset 和 serializers 用来被继承后重写,

-- 单条的再写单独的类

1.4 注意返回 queryset 的时候加上 .all() 方法

1.5 注意返回序列化函数的时候设置参数 *args,**kwargs

1.6 命名规范

--GenericAPIView 用于被继承重写,关键词 Generic

--XxxModelMixin 单独继承无意义,关键词 ModelMixin

代码语言:javascript
复制
from rest_framework.viewsets import ViewSetMixin

from DjangoDemo.models import Book
from rest_framework.views import APIView, Response
from SerDemo.serializers import BookSerializer
from rest_framework import views

"""""""""""""""全局第一次&第二次封装"""""""""""""""


class GenericAPIView(APIView):
    """
    Generic
    第一次封装
    step1: 父类参数不同,定义为None,让子类重写
    """
    queryset = None
    serializers_class = None

    # 定制函数返回queryset
    def get_queryset(self):
        return self.queryset.all()  # django 的坑

    # 定制函数返回序列化类
    def get_serializers(self, *args, **kwargs):
        return self.serializers_class(*args, **kwargs)


# 展示逻辑
class ListModelMixin(GenericAPIView):  # Mixin
    def list(self, request):
        queryset = self.get_queryset()
        ser_obj = self.get_serializers(queryset, many=True)
        return Response(ser_obj.data)


# 创建逻辑
class CreateModelMixin(GenericAPIView):
    def create(self, request):
        ser_obj = self.get_serializers(data=request.data)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.validated_data)
        else:
            return Response(ser_obj.errors)


# 第二次封装只是方便继承
class ListCreateAPIView(ListModelMixin, CreateModelMixin):
    pass


# 对某一批书籍查询&新建书籍
class BookView(ListCreateAPIView):
    """
    step2: 继承类并对参数重写
    子类将用够父类的全部方法
    """
    queryset = Book.objects.all()
    serializers_class = BookSerializer

    # def get(self, request):
    #     # 调用外部的get方法
    #     book_queryset = Book.objects.all()
    #     # 用序列化器进行序列化
    #     ser_obj = BookSerializer(book_queryset, many=True)
    #     return Response(ser_obj.data)

    # 增加图书的视图
    # post验证反序列化的校验
    # 注意save
    def get(self, request):
        return self.list(request)

    # def post(self, request):
    #     # 接口传过来的data在request.data里面
    #     # 用序列化器对post参数进行字段的额校验
    #     ser_obj = BookSerializer(data=request.data)
    #     if ser_obj.is_valid():
    #         ser_obj.save()
    #         return Response(ser_obj.validated_data)
    #     else:
    #         return Response(ser_obj.errors)
    def post(self, request):
        return self.create(request)


"""""""""""""""多条&单条分割线"""""""""""""""


# 查看单条类
class RetrieveModelMixin(GenericAPIView):
    def retrieve(self, request, pk):
        book_obj = self.get_queryset().filter(id=pk).first()
        ser_obj = self.get_serializers(book_obj)
        return Response(ser_obj.data)


# 更新单条类
class UpdateModelMixin(GenericAPIView):
    def update(self, request, pk):
        book_obj = self.get_queryset().filter(id=pk).first()
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response('校验之后的数据是-->{}'.format(ser_obj.validated_data))
        return Response('校验失败,失败信息-->{}'.format(ser_obj.errors))


# 删除单条类
class DestroyModelMixin(GenericAPIView):
    def destroy(self, request, pk):
        book_obj = self.get_queryset().filter(id=pk).first()
        if not book_obj:
            return Response('删除书籍不存在')
        book_obj.delete()
        return Response('书籍删除成功!')


# 第二次封装只是方便继承
class RetrieveUpdateDestroyAPIView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


# 对某一条数据查询和编辑
class BookEditView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Book.objects.all()
    serializers_class = BookSerializer

    # def get(self, request, obj_id):
    #     book_obj = Book.objects.filter(id=obj_id).first()
    #     ser_obj = BookSerializer(book_obj)
    #     return Response(ser_obj.data)
    def get(self, request, pk):
        return self.retrieve(request, pk)

    # def put(self, request, obj_id):
    #     book_obj = Book.objects.filter(id=obj_id).first()
    #     "put请求进行编辑"
    #     "instance对象,data数据,partial参数"
    #     ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
    #     if ser_obj.is_valid():
    #         ser_obj.save()
    #         return Response('校验之后的数据是-->{}'.format(ser_obj.validated_data))
    #     return Response('校验失败,失败信息-->{}'.format(ser_obj.errors))
    def put(self, request, pk):
        return self.update(request, pk)

    # def delete(self, request, obj_id):
    #     book_obj = Book.objects.filter(id=obj_id).first()
    #     if not book_obj:
    #         return Response('删除书籍不存在')
    #     book_obj.delete()
    #     return Response('书籍删除成功!')
    def delete(self, request, pk):
        return self.destroy(request, pk)

2.第三次封装(接上面的代码),一般就是用到第二层的封装,第三层封装基本不怎么用

2.1 第三层封装在视图中

2.1.1 写一个类继承所有的二次封装类

2.1.2 再继承一个 ViewSetMixin 类,from rest_framework.viewsets import ViewSetMixin

2.1.3 写一个类继承这个三次封装的类,同样配置 queryset 和 serializer_class

代码语言:javascript
复制
"""""""""""""""全局第三次封装"""""""""""""""""


# 继承 ViewSetMixin(from rest_framework.viewsets import ViewSetMixin) 和 上面第二次只继承的 pass 类
class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    pass


# 对全局APIView进行第三次封装
class BookModelView(ModelViewSet):
    # 同样配置 queryset 和 serializer_class
    queryset = Book.objects.all()
    serializers_class = BookSerializer

2.2 封装类在url里面配置传参(注意 id 用 pk 代替,不要使用 id)

2.2.1 将views里面写的第三次封装的BookModelView拿过来 2.2.2 大坑!id全部使用 pk 来代替 2.2.3 参数接受一个字典,键值分别是 请求方式:处理逻辑的函数名

代码语言:javascript
复制
"""将views里面写的第三次封装的BookModelView拿过来"""
"""大坑!id全部使用 pk 来代替"""
"""参数接受一个字典,键值分别是  请求方式:处理逻辑的函数名 """
urlpatterns = [
    url(r'book/$', views.BookModelView.as_view({"get": "list", "post": "create"})),
    url(r'book/(?P<pk>\d+)', views.BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]

2.路由组件(在url里面使用,基本不怎么使用)

代码语言:javascript
复制
# 帮助我们生成带参数的路由
from rest_framework.routers import DefaultRouter
# 实例化DefaultRouter对象
router = DefaultRouter()
# 注册我们的路由以及视图
router.register(r'^book', views.BookModelView)
# urlpatterns += router.urls

3.版本控制

3.1 版本控制是在请求到达视图之前确定版本号,方便视图做逻辑判断

代码语言:javascript
复制

class MyVersion(object):
    @staticmethod
    # 固定函数名称,在请求到达视图之前对版本进行控制
    def determine_version(request, *args, **kwargs):
        # 方法的返回值是版本号
        # 获取前端传过来的版本号 并且把版本号返回
        version = request.query_params.get("version")
        if not version:
            version = "v1"
        return version

3.2 settings配置信息

代码语言:javascript
复制
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [],
    # 对版本控制类配置
    "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion",
    # 默认版本
    'DEFAULT_VERSION': None,
    # 允许的版本
    'ALLOWED_VERSIONS': None,
    'VERSION_PARAM': 'version'
}

3.3 视图中打印版本信息

代码语言:javascript
复制
# Create your views here.
from rest_framework.response import Response
from rest_framework.views import APIView


class VersionDemo(APIView):
    # 这里也可以对单独的某个视图请求配置版本
    # versioning_class = MyVersion
    def get(self, request):
        print('当前版本-->', request.version)
        # scheme我配置的版本控制类的实例化对象
        print(request.versioning_scheme)
        return Response('版本控制接口')

3.4 其他的几种 version 传参方式

代码语言:javascript
复制
# 进入 versioning
from rest_framework import versioning

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.视图的第一次封装和第二次封装
    • 1.第一次封装和第二次封装(第二次封装仅仅是整合继承类)
      • 2.第三次封装(接上面的代码),一般就是用到第二层的封装,第三层封装基本不怎么用
        • 2.1 第三层封装在视图中
        • 2.2 封装类在url里面配置传参(注意 id 用 pk 代替,不要使用 id)
    • 2.路由组件(在url里面使用,基本不怎么使用)
    • 3.版本控制
      • 3.1 版本控制是在请求到达视图之前确定版本号,方便视图做逻辑判断
        • 3.2 settings配置信息
          • 3.3 视图中打印版本信息
            • 3.4 其他的几种 version 传参方式
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档