设为首页 收藏本站
查看: 478|回复: 0

Django中drf的自动生成路由和认证源码刨析

[复制链接]
累计签到:504 天
连续签到:1 天
发表于 2022-12-25 20:59:26 | 显示全部楼层 |阅读模式
## 1 路由
# 1 在urls.py中配置
    path('books4/', views.Book4View.as_view()),
    re_path('books4/(?P<pk>\d+)', views.Book4DetailView.as_view()),
# 2 一旦视图类,继承了ViewSetMixin,路由
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5Viewlist方法
    re_path('books5/(?P<pk>\d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),

# 3 继承自视图类,ModelViewSet的路由写法(自动生成路由)
-urls.py
    # 第一步:导入routers模块
    from rest_framework import routers
    # 第二步:有两个类,实例化得到对象
    # routers.DefaultRouter 生成的路由更多
    # routers.SimpleRouter
    router=routers.DefaultRouter()
    SimpleRouter会生成两条路由
    <URLPattern '^books/$' [name='book-list']>,
    <URLPattern '^books/(?P<pk>[^/.]+)/$'[name='book-detail']>
    DefaultRouter生成6条路由
    ^books/$ [name='book-list']
    ^books/(?P<pk>[^/.]+)/$ [name='book-detail']  这两条跟simple一样
    ^$ [name='api-root']  根,根路径会显示出所有可以访问的地址
    ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
    ^books\.(?P<format>[a-z0-9]+)/?$ [name='book-list']  http://127.0.0.1:8000/books.json
    ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail']  http://127.0.0.1:8000/books/1.json
-
    # 第三步:注册
    # router.register('前缀','继承自ModelViewSet视图类','别名')
    router.register('books',views.BookViewSet) # 不要加斜杠了
    # 第四步
    # router.urls # 自动生成的路由,加入到原路由中
    # print(router.urls)
    # urlpatterns+=router.urls[列表相加,也可以用for循环就是比较麻烦,要for循环两次][字典相加用update方法]
    '''
-views.py
    from rest_framework.viewsets import ModelViewSet
    from app01.models import Book
    from app01.ser import BookSerializer
    class BookViewSet(ModelViewSet):
        queryset =Book.objects
        serializer_class = BookSerializer

### 1.1 action的使用

# action干什么用?为了给继承自ModelViewSet的视图类中定义的函数也添加路由
# 使用
class BookViewSet(ModelViewSet):
    queryset =Book.objects.all()
    serializer_class = BookSerializer
    # methods第一个参数,传一个列表,列表中放请求方式,
    # ^books/get_1/$ [name='book-get-1'] 当向这个地址发送get请求,会执行下面的函数
    # detail:布尔类型 如果是True
    #^books/(?P<pk>[^/.]+)/get_1/$ [name='book-get-1']
    @action(methods=['GET','POST'],detail=True)
    def get_1(self,request,pk):
        print(pk)
        book=self.get_queryset()[:2]  # 从0开始截取一条
        ser=self.get_serializer(book,many=True)
        return Response(ser.data)
   
# 装饰器,放在被装饰的函数上方,method:请求方式,detail:是否带pk


### 2.2  认证的源码分析
#1 APIVIew----》dispatch方法---》self.initial(request, *args, **kwargs)包装成新的reqeust---->有认证,权限,频率
#2 只读认证源码: self.perform_authentication(request) 这个目前还在APIview类中,找还是先从自己的视图类中找
#3 self.perform_authentication(request)就一句话:request.user,需要去drf的Request对象中找user属性(方法)
#4 Request类中的user方法,刚开始来,没有_user,走 self._authenticate(),通过drf的Request中发现.user有@name.setattr这个是放值,我们要用取值的方法
def user(self):
    if no hasattr(self,'_user'):如果request没有_user走下面判断
        with wrap_attributeerrors():
            self._authenticate() 走Request的这个方法
    return self._user
#5 核心,就是Request类的 _authenticate(self):
    def _authenticate(self):
        # self.authenticators配置的一堆认证类产生的认证类对象组成的 list
        # self.authenticators 你在视图类中配置的一个个的认证类:authentication_classes=[认证类1,认证类,对象的列表
        for authenticator in self.authenticators:
            [# self.authenticators---》先去Request中找,发现在__init__中,当作参数传进来的,说明在初始化的时候被传进来的--》上一层dispatch中,发现在APIview的里面中有这个方法get_authenticators方法,是一个列表生成式[对象1,对象]
            try:
                # 认证器(对象)调用认证方法authenticate(认证类对象self, request请求对象)
                # 返回值:登陆的用户与认证的信息组成的 tuple
                # 该方法被try包裹,代表该方法会抛异常,抛异常就代表认证失败
                user_auth_tuple = authenticator.authenticate(self) # [注意这selfRequest对象所以写authenticate时会把request也会闯过了,认证对象调用自己的authenticate方法也会把认证类自动传进来]
            except exceptions.APIException:
                self._not_authenticated()
                raise
            # 返回值的处理
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                # 如何有返回值,就将 登陆用户 与 登陆认证 分别保存到 request.user、request.auth
                self.user, self.auth = user_auth_tuple
                return
        # 如果返回值user_auth_tuple为空,代表认证通过,但是没有 登陆用户 与 登陆认证信息,代表游客
        self._not_authenticated()

### 2.3 认证组件的使用

# 写一个认证类 app_auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken
class MyAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 认证逻辑,如果认证通过,返回两个值
        #如果认证失败,抛出AuthenticationFailed异常
        token=request.GET.get('token')
        if  token:
            user_token=UserToken.objects.filter(token=token).first()
            # 认证通过
            if user_token:
                return user_token.user,token[user_token.user这个就是为什么request.user可以拿到当前用户的对象,.user跨表到User用户对象里面去了]
            else:
                raise AuthenticationFailed('认证失败')
        else:
            raise AuthenticationFailed('请求地址中需要携带token')

# 可以有多个认证,从左到右依次执行
# 全局使用,在setting.py中配置
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",]
}
# 局部使用,在视图类上写
authentication_classes=[MyAuthentication]
# 局部禁用
authentication_classes=[]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1003453-1-1.html 上篇帖子: Django-drf中详解Request对象和Response对象、初始GenericAPIView 下篇帖子: Django中drf三大组件:认证组件、权限组件、频率组件、Response
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表