restfull规范、DRF视图和路由

一、restfull规范的简单介绍

1、介绍

REST:表述性状态转移,是一种web交互方案

资源:在web中只要有被引用的必要都是资源

URI:
  URI 统一资源标识符
  URL 统一资源定位符

统一资源接口
  根据HTTP请求方式的不同对资源进行不同的操作
  遵循HTTP请求方式的语义

前后端传输的叫资源的表述

前端展现的叫资源的状态

通过超链接的指引告诉用户接下来有哪些资源状态可以进入

2、restfull规范

复制代码
核心思想
    -- 面向资源去编程
        每个url就是资源的体现 尽量用名词不要用动词
    -- 根据HTTP请求方式的不同对资源进行不同的操作

URL体现
    -- 版本
        https://v3.bootcss.com
        https://bootcss.com/v3
    -- 体现是否是API
        https://v3.bootcss.com/api
    -- 过滤信息
        https://v3.bootcss.com?page=1
    -- 尽量用HTTPS

返回值体现
    -- 携带状态码
    -- 携带错误信息
    -- 返回值
        get  返回查看的所有或者单条信息
        post 返回新增的那条数据
        put/patch 返回更新那条数据
        delete  返回空
    -- 携带超链接
复制代码

 

二、DRF的视图的封装

1、为什么要封装

当有很多个表进行增删改查时,实际上很多代码都是相同的,只是要获取的queryset和序列化器等不同,这就导致我们的视图有特别多重复的代码,
因此对视图进行封装,可减少代码的冗余。

 

2、要封装的原视图

复制代码
class BookView(APIView):
    def get(self, request):
        book_queryset = Book.objects.all()
        ser_obj = BookSerializer(book_queryset, many=True)
        return Response(ser_obj.data)

    # 新增书籍
    def post(self, request):
        book_obj = request.data
        ser_obj = BookSerializer(data=book_obj)
        if ser_obj.is_valid():
            ser_obj.save()
            print(ser_obj.validated_data)
            return Response(ser_obj.data)
        # 校验不通过返回错误信息
        return Response(ser_obj.errors)

# 编辑书籍
class BookEditView(APIView):
    def get(self, request, id):
        book_obj = Book.objects.filter(pk=id).first()
        ser_obj = BookSerializer(book_obj)
        return Response(ser_obj.data)

    def put(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        return Response(ser_obj.errors)

    def delete(self, request, id):
        book_obj = Book.objects.filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response('')
        return Response('删除对象不存在')
View Code
复制代码

 

3、第一次封装

复制代码
# 获取query_set和序列化器的类
class GenericAPIView(APIView):
    query_set = None
    serializer_class = None

    def get_queryset(self):
        return self.query_set

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


# 实现get方法的类
# 小知识点:一般Mixin代表的是混合类,单独继承ListModelMixin你去哪里找get_queryset方法
# 因此,其他类继承Mixin类的时候,还应该多继承其他的某些类
class ListModelMixin(object):
    def list(self, request):
        queryset = self.get_queryset()
        ser_obj = self.get_serializer(queryset, many=True)
        return Response(ser_obj.data)


# 实现post方法的类
class CreateModelMixin(object):
    def create(self, request):
        # 获取前端传过来的数据
        obj = request.data
        # 用序列化器做校验
        ser_obj = self.get_serializer(data=obj)
        if ser_obj.is_valid():
            # 校验通过,新增书籍
            ser_obj.save()  # 这里的save方法会去调用序列化器的create方法
            print(ser_obj.validated_data)  # validated_data是通过校验的数据,也会封装到data里面
            return Response(ser_obj.data)
        # 校验不通过返回错误信息
        return Response(ser_obj.errors)


# 实现编辑的get方法的类
class RetrieveModelMixin(object):
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(pk=id).first()
        ser_obj = self.get_serializer(book_obj)
        return Response(ser_obj.data)


# 实现编辑的put方法的类
class UpdateModelMixin(object):
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True)
        if ser_obj.is_valid():
            ser_obj.save()
            return Response(ser_obj.data)
        return Response(ser_obj.errors)


# 实现删除delete方法的类
class DestroyModelMixin(object):
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        if book_obj:
            book_obj.delete()
            return Response("")
        return Response("删除的对象不存在")


# 书籍列表
class BookView(GenericAPIView,ListModelMixin, CreateModelMixin):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        return self.retrieve(request, id)

    def put(self, request, id):
        return self.update(request, id)

    def delete(self, request, id):
        return self.destroy(request, id)
View Code
复制代码

 

4、第二次封装

由于上面的继承太长了,因此我们细化一点点,其实就是在第一次封装的基础上另外设置一些类来进行了继承。

复制代码
# 继承上面需要的类,别的类只需继承这个类即可使用这个类继承的方法
class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin):
    pass

class RetrieveUpdateDestroyModelMixin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


# 书籍列表
class BookView(ListCreateModelMixin):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)


class BookEditView(RetrieveUpdateDestroyModelMixin):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        return self.retrieve(request, id)

    def put(self, request, id):
        return self.update(request, id)

    def delete(self, request, id):
        return self.destroy(request, id)
复制代码

 

5、第三次封装

复制代码
1. DRF框架的ViewSetMixin类重写了CBV的as_view方法,使其可以接收参数,路由分发的时候会根据参数进行分发,
继承了ViewSetMixin的类,它的路由as_view可以传参

2. urls.py
from django.conf.urls import url
from libsys import views

urlpatterns = [
    url(r'^list/$', views.BookModelView.as_view({"get": "list", "post": "create"})),
    url(r'^retrieve/(?P<id>\d+)/$', views.BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]


3. 第三次封装
from rest_framework.viewsets import ViewSetMixin  # 重写as_view使其可以传参

# 继承上面需要的类,别的类只需继承这个类即可使用这个类继承的方法
class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin):
    pass

class RetrieveUpdateDestroyModelMixin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


# 五合一的视图
# ViewSetMixin必须在GenericAPIView前面,因为需要ViewSetMixin先做路由的分发
class ModelViewSet(ViewSetMixin, ListCreateModelMixin, RetrieveUpdateDestroyModelMixin):
    pass

class BookModelView(ModelViewSet):
    # 这里什么都不用写了,因为as_view重写后,某个请求进来会默认去找它对应的方法
    # 这里找不到,就会去父类中找
    query_set = Book.objects.all()
    serializer_class = BookSerializer
复制代码

 

6、使用DRF框架帮我们封装好的模块

复制代码
1. 直接使用DRF自带的ModelViewSet(DRF的ModelViewSet也是继承了ViewSetMixin和那6个方法的类,即ModelViewSet是7合1的类)
注意:
    DRF中使用queryset,我们自定义的是query_set
    用框架封装的视图,我们url上的那个关键字参数要用pk,系统默认的

2. urls.py
from django.conf.urls import url
from libsys import views

urlpatterns = [
    url(r'^list/$', views.BookModelView.as_view({"get": "list", "post": "create"})),
    url(r'^retrieve/(?P<pk>\d+)/$', views.BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]

3. 视图
from rest_framework.viewsets import ModelViewSet  # 这里的ModelViewSet是DRF给我们的类

class BookModelView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
复制代码

 

三、路由

复制代码
from rest_framework.routers import DefaultRouter
第一步实例化对象
router = DefaultRouter()

第二步把路由以及视图注册到对象
router.register('list', views.BookModelView)  # 路径,视图

第三步生成可传参的路由
urlpatterns += router.urls

注意:用默认生成的路由,必须保证你的视图函数是继承了ViewSetMixin,即你的as_view方法是可以传参的

在浏览器中就可以输入:
list/
list/1
list/2
...

还额外生成了不用模板的数据路由
list.json
list/1.json
复制代码

 

四、DRF框架视图类

1、DRF给我们提供的所有视图,都在这几个模块下

from rest_framework import views
from rest_framework import viewsets
from rest_framework import mixins
from rest_framework import generics

 

2、这几个模块主要封装的类

复制代码
from rest_framework import views
# 封装了APIView
class APIView(View)


from rest_framework import generics
# 封装了我们获取queryset和serializer_class方法的类
class GenericAPIView(views.APIView):
    def get_queryset()
    def get_object()
    def get_serializer()


from rest_framework import mixins
# 封装了我们请求的5个方法的类
# 获取全部:{"get": "list", "post": "create"}
# 编辑和删除某个对象:{"get": "retrieve", "put": "update", "delete": "destroy"}

# 创建新对象
class CreateModelMixin(object)

# 获取所有对象
class ListModelMixin(object)

# 获取指定编辑的对象
class RetrieveModelMixin(object)

# 更新指定编辑的对象
class UpdateModelMixin(object)

# 删除指定的对象
class DestroyModelMixin(object)


from rest_framework import viewsets
# 封装了ViewSetMixin,使得CBV的as_view方法或根据http请求去执行对应的方法(mixins的那五个方法)
class ViewSetMixin(object)

class GenericViewSet(ViewSetMixin, generics.GenericAPIView)

# ModelViewSet继承了所有方法,即:我们视图继承了ModelViewSet,那么增删改查方法已经默认写好了
# 只要as_view对http方法进行分发即可。即ModelViewSet是7合1的类
class ModelViewSet(
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    mixins.ListModelMixin,
    GenericViewSet,
)
复制代码

 

3、ModelViewSet

posted @   我用python写Bug  阅读(507)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示