django框架之drf(部分讲解)

一、各个视图子类

  • 两个视图基类

  • 五个视图扩展类

  • 九个视图子类-----》视图类,不需要额外继承GenericAPIView,只需要继承九个州其中之一,就会有某个或某几个接口

路由

urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookView.as_view()),
]

视图类

class BookView(ListCreateAPIView):	# 查询所有,新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

新增一个,修改一个,删除一个

class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

二、视图集

(1)、通过ModelViewSet编写五个接口

路由

urlpatterns = [
    path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

视图类

class BookView(ModelViewSet):	# 查询所有,新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

(2)、通过ReadOnlyModelViewSet编写两个只读接口

路由

urlpatterns = [
    path('books/', views.BookView.as_view({'get': 'list'})),
    path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve'})),
]

视图类

class BookView(ReadOnlyModelViewSet):	# 查询所有,新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

(3)、ViewSetMixin源码分析

# 请求来了,路由匹配成功---》get请求,匹配成功books,会执行  views.BookView.as_view({'get': 'list', 'post': 'create'})()------>读as_view【这个as_view是ViewSetMixin的as_view】

    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        # 如果没有传actions,直接抛异常,路由写法变了后,as_view中不传字典,直接报错
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
		# 。。。。其他代码不用看
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if 'get' in actions and 'head' not in actions:
                actions['head'] = actions['get']
            self.action_map = actions
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs)
        # 去除了csrf校验
        return csrf_exempt(view)
    
    
# 路由匹配成功执行views.BookView.as_view({'get': 'list', 'post': 'create'})()----》本质执
行ViewSetMixin----》as_view----》内的view()---》代码贴过来
    def view(request, *args, **kwargs):
            #actions 是传入的字典--->{'get': 'list', 'post': 'create'}
            self.action_map = actions
            # 第一次循环:method:get,action:list
            # 第一次循环:method:post,action:create
            for method, action in actions.items():
                # 反射:去视图类中反射,action对应的方法,action第一次是list,去视图类中反射list方法
                # handler就是视图类中的list方法
                handler = getattr(self, action)
                # 反射修改:把method:get请求方法,handler:list
                # 视图类的对象的get方法,变成了list
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs) #dispatch是APIView的

总结:

  • 只要继承ViewSetMixin的视图类,路由写法就变了(重写了as_view)
  • 变成需要传入字典映射方法:
    • 只要传入actions,以后访问get就是访问list,访问post,就是访问create
  • 其他执行跟之前一样
  • 以前视图类类中的方法名,可以任意命名,只要在路由中做好映射即可【重要】

(4)、from rest_framework.viewsets包下的类

'''
from rest_framework.viewsets下有这几个类
ModelViewSet:5个试图扩展类+ViewSetMixin+GenericAPIView
ReadOnlyModelViewSet::2个试图扩展类+ViewSetMixin+GenericAPIView   只读的两个
ViewSetMixin:魔法,重新了as_view,只要继承他,以后路由写法变成了映射方法
ViewSet:ViewSetMixin+ APIView
GenericViewSet:ViewSetMixin+ GenericAPIView
'''

重点

  • 以后,你想继承APIView,但是想变路由写法【视图类中方法名任意命名】,要继承ViewSet
  • 以后,你想继承GenericAPIView,但是想变路由写法【视图类中方法名任意命名】,要继承GenericViewSet

(5)、视图层大总结

1. 两个视图基类

APIView
GenericAPIView

2. 五个视图扩展类,不是视图类,必须配合GenericAPIView
3. 九个视图子类,是视图类,只需要继承其中某一个即可
4. 视图集

-ModelViewSet:路由写法变了,只需要写两行,5个接口都有了

-ReadOnlyModelViewSet:路由写法变了,只需要写两行,2个只读接口都有了

-ViewSetMixin:不是视图类,魔法,重写了as_view,路由写法变了,变成映射了
	views.BookView.as_view({'get': 'list', 'post': 'create'})

-ViewSet:ViewSetMixin+ APIView

-GenericViewSet:ViewSetMixin+ GenericAPIView

三、路由系统

(1)、自动生成路由

# def 由于继承ViewSetMinxin类,路由写法变了
	-原生+drf,以后的路由写法,可能会有如下情况(三种情况)
		-path('books/', views.BookView.as_view())
		-path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'}))
		-自动生成


# drf提供了两个路由类,继承ModelViewSet后,路由可以自动生成

使用步骤

  • 第一步:导入路由类
  • 第二步:实例化得到对象(两个类,一般使用SimpleRouter)
  • 第三步:注册:router.register('books', views.BookView, 'books')
  • 第四步:在urlpatterns中注册,两种方式
urlpatterns +=router.urls
include:path('/api/v1/', include(router.urls))

底层实现:自动生成路由

get--->list
get---->retrieve
put---->update
post---->create
delete---->destory
ModelViewSet,ReadOnlyModelViewSet可以自动生成

九个视图子类+配合ViewSetMixin	才可以自动生成
GenericAPIView+五个视图扩展类+配合ViewSetMixin	才能自动生成

(2)、action 装饰器

# action 写在视图类的方法上,可以自动生成路由

# 使用步骤
	- 1 写在视图类方法上
    class SendView(ViewSet):
        # methods指定请求方法,可以传多个
        # detail:只能传True和False
        	-False,不带id的路径:send/send_sms/
            -True,带id的路径:send/2/send_sms/
        #url_path:生成send后路径的名字,默认以方法名命名 
        # url_name:别名,反向解析使用,了解即可
        @action(methods=['POST'], detail=False)
        def send_sms(self, request):
            
            
 # 以后看到的drf路由写法
	后期,都是自动生成,一般不在urlpatterns 加入路由了

补充:

	-1 不同请求方式可以使用不同序列化类
	-2 不同action使用不同序列化类
class SendView(GenericViewSet):
    queryset = None
    serializer_class = '序列化类'

    def get_serializer(self, *args, **kwargs):
        if self.action=='lqz':
            return '某个序列化类'
        else:
            return '另一个序列化列'
    @action(methods=['GET'], detail=True)
    def send_sms(self, request,pk):
        print(pk)
        # 手机号,从哪去,假设get请求,携带了参数
        phone = request.query_params.get('phone')
        print('发送成功,%s' % phone)
        return Response({'code': 100, 'msg': '发送成功'})

    @action(methods=['GET'], detail=True)
    def lqz(self,request):  # get
        # 序列化类
        pass

    @action(methods=['GET'], detail=True)
    def login(self,request):  # get
        # 序列化类
        pass

四、认证组件

访问某个接口,需要登陆后才能访问

# 第一步:写个登录功能,用户表
	-User表
	-UserToken表:存储用户登录状态 [这个表可以没有,如果没有,把字段直接写在User表上也可以]

(1)、登录接口

表模型

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)



class UserToken(models.Model):  # 跟User是一对一
    token = models.CharField(max_length=32)
    user = models.OneToOneField(to='User', on_delete=models.CASCADE, null=True)
    # user :反向,表名小写,所有有user字段

路由

router.register('user', views.UserView, 'user')  # /api/v1/user/login     post 请求

视图类

### 登录接口  自动生成路由+由于登录功能,不用序列化,继承ViewSet
from .models import User, UserToken
import uuid


class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 用户存在,登录成功
            # 生成一个随机字符串--uuid
            token = str(uuid.uuid4())  # 生成一个永不重复的随机字符串
            # 在userToken表中存储一下:1 从来没有登录过,插入一条,     2 登录过,修改记录
            # 如果有就修改,如果没有就新增  (if 自己写)
            # kwargs 传入的东西查找,能找到,使用defaults的更新,否则新增一条
            UserToken.objects.update_or_create(user=user, defaults={'token': token})
            return Response({'code': '100', 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': '101', 'msg': '用户名或密码错误'})
posted @   吴仁耀  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
  1. 1 原来你也在这里 周笔畅
  2. 2 世间美好与你环环相扣 柏松
  3. 3 起风了 吴青峰
  4. 4 极恶都市 夏日入侵企划
极恶都市 - 夏日入侵企划
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 王星

作曲 : 灰鸿啊/皮皮

编曲 : 夏日入侵企画

制作人 : 邢硕

节奏吉他 : 肯尼

主音吉他 : 张伟楠

贝斯 : 皮皮

鼓 : 海鑫

和声 : 邢硕

音效制作 : 邢硕

录音 : 邢硕/夏国兴

混音 : 于昊

特别鸣谢 : 张伟楠

这城市的车流和这地表的颤抖

像一颗石子落入地心之后泛起的温柔

暗涌

河水流过转角她的楼

被梦魇

轻声呓语唤醒身后的幼兽

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都

已忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去陈旧的还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池已失守

最终无法占有

无眠辗转

伴着人间破碎的旧梦

像繁星

退却后只剩下混沌的夜空

炙热

掩盖风声鹤唳的担忧

把所有失落无助反手推入

无尽的白昼

失效感官焦灼只剩下

麻木愚钝无从感受

共同支撑全都瓦解

只是我们现在都已经忘记到底是

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

眼看这情节开始变旧

所有的城池早已失守

惶恐难以接受

缠绵往复不肯放手

最终无法占有

谁隐藏春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁 灭 即 拯 救

谁掠夺春秋

谁在大雨之后

把旗帜插在最高的楼

过去的陈旧还在坚守

内心已腐朽

摇摇欲坠不停退后

毁灭即拯救

夏日掠夺春秋

结局无法看透

明知城池已失守

缠绵往复不肯放手

最终无法占有

点击右上角即可分享
微信分享提示