前面讲了session机制,作为登录状态保持:
- 那么既然登录状态已经保持了? 我们为什还要去判断,用户请求接口时 是否登录呢?
- 我希望大家不要迷惑这些。session机制,只是保存用户的信息,并且交由 客户端一个 sessionid,用来验证用户已登录。 这一过程:我认为是发生在中间件当中的。 在django生成 request 对象的时候, 前端携带 带有sessionid的 cookie,经过处理,验证通过,说明已登录。并开始构造当前登录用户的对象 request.user, 若未验证通过,则request.user 表示的则是一个匿名用户。
- 而这仅仅是django知道了,是都当前已经有用户登录进来。我们的接口并不知道这些。在一些需要登录才能访问的请求当中,我们需要自己 在视图当中 使用相关的 方法 进行验证用户以登录。
原始的登录判断方法 is_authenticated():
实际例子:
- 很简单通过判断 返回的结果是 True 还是 Flase 判断是否登录。
- 缺点:
- 登录验证逻辑很多地方都需要,所以该代码需要重复编码好多次。
login_required装饰器
- 内部封装了is_authenticate
- 位置:django.contrib.auth.decorators
- 作用于函数
- 先看下文档的介绍
- 很清楚,一共有两个值得注意的参数
- (1)login_url , 这是验证失败后跳转的地址
- (2) ‘next’ :这是 login_url 链接中的,一个参数,用于登录成功之后的跳转。
- 当然,后面提到这个 参数next 的名字,可以自己更改。
问题来了
-
我们定义的视图 是 类视图,所以要对 装饰器进行一些封装
-
方法: 要想使用login_required装饰器装饰类视图,可以间接的**装饰as_view()**方法的返回值,以达到预期效果
-
首先了解 as_view() 方法的用处
view函数主要做了两件事情,一是实例化一个类视图对象,这个容易理解,是哪个类视图对象接收了请求那就实例化哪个。二是调用dispatch方法,根据http请求方法(比如get,post)分派处理函数 -
也就是说,as_view()方法返回的就是类视图中的某个所请求的方法。 这就可以使用装饰器进行封装了。
实现:代码
- 我们新定义文件,里面写重新封装的代码
class LoginRequired(object):
"""验证用户是否登陆"""
@classmethod
def as_view(cls, **initkwargs):
# 自定义as_view()方法中,调用父类的as_view()方法
view = super().as_view()
return login_required(view)
# 视图例子
class UserInfoView(LoginRequired, View):
"""用户中心"""
def get(self, request):
"""提供个人信息界面"""
return render(request, 'user_center_info.html')
- (1) 封装的 LoginRequired,放在第一个位置!
- (2)这就是巧妙之处! LoginRequired,中用用了 super调用父类的as_view( ) 方法,要知道,继承的可是 object?? 哪里来的这个方法?
- 这就要提到python多继承中的 顺序(MRO),使用C3算法。大家详细的可以去查看官方文档。
- 因为(1)我们启动的是视图类 UserInfoView,所以当执行 as_view() 方法时,调用LoginRequired中定义的 as_view() 方法(2)此时的MRO顺序当中, 他的继承父类 先是View类! 所以继承该方法,最终实现 登陆验证的操作。
同时注意在settings中 配置 上面讲的 login_url 配置项,以及next参数的跳转即完成啦!
over!