login_required装饰器

Django用户认证系统提供了 login_required 函数装饰器来限制页面的访问,使用 login_required 装饰器的视图函数的页面,只有登录的用户可以访问。login_required 装饰器定义在 django.contrib.auth.decorators 模块中,内部封装了 is_authenticated 来判断用户是否登录。
如果已经登录则进入内部视图,执行视图函数逻辑。
如果未登录默认被重定向到 setting.LOGIN_URL 配置项指定的地址。

1、login_required 装饰函数视图

from django.contrib.auth.decorators import login_required

@login_required(login_url=reverse('users:login'))
def userinfo_view(request):
	return render(request, "user_center_info.html")

login_required 装饰器可以装饰一个视图函数(接收request参数,返回response响应的函数),如果request中的user已经登录,就返回视图函数返回response,如果request中的user是匿名用户,就返回重定向页面。

2、login_required 装饰类视图
login_required装饰器可以直接装饰函数视图,但是不能直接装饰类视图。

login_required装饰器的本质是把要装饰的函数对象传入login_required()函数中,函数返回被装饰过的函数对象,所以只要能够拿到函数视图的函数对象,就可以使用 login_required 来装饰。

类视图的as_view()方法就是将类视图转成函数视图,as_view()方法的返回值是一个函数对象,要想使用 login_required装饰器 来装饰类视图,可以间接的装饰 as_view()方法 的返回值。

接下来,来聊一聊具体怎么使用装饰器来装饰类视图。

第一种方式,as_view()方法是在url配置的时候调用的,所以可以在url配置的时候装饰as_view()方法的返回值。

# urls.py
re_path("info/$", login_required(views.UserCenterView.as_view()), name="info"),

# views.py
class UserInfoView(View):
	"""用户中心"""
	def get(self, request):
		"""提供个人信息界面"""
		return render(request, "user_center_info.html")

第二种方式,在类继承的时候,我们可以通过super.as_view()方法调用as_view()方法,并且得到函数视图,所以我们还可以通过类继承来使用login_required装饰as_view()返回值。

# urls.py中不用login_required来装饰
re_path("info/$", views.UserCenterView.as_view(), name="info"),

这里提供三种方案的思路来实现第二种方式的逻辑。

方案一:UserInfoView里面重写as_view()方法,使用login_required装饰super.as_view()返回值
login_required装饰器_第1张图片

# views.py
class UserCenterView(View):

    @classmethod
    def as_view(cls, **initkwargs):
        view = super().as_view()
        return login_required(view)   # 类视图的装饰方法

    def get(self, request: HttpRequest):
        """打开用户中心页面"""
        return render(request, "user_center_info.html")

总结:每个需要验证用户是否登录的页面都需要重写as_view方法。

方案二:UserInfoView -> LoginRequiredView -> View,在LoginRequiredView里面重写as_view()方法,使用 login_required 装饰 super.as_view()返回值。
login_required装饰器_第2张图片

# views.py
class LoginRequiredView(View):
	"""验证用户是否登录"""
	@classmethod
	def as_view(cls, *args, **kwargs):
		# 自定义的as_view()方法中,调用父类的as_view()方法
		view = super.as_view(*args, **kwargs)
		return login_required(view)

class UserCenterView(LoginRequiredView):
	"""用户中心"""
    def get(self, request: HttpRequest):
        """打开用户中心页面"""
        return render(request, "user_center_info.html")

总结:LoginRequiredView(object)依赖于视图类View,但我们不会单独使用LoginRequiredView来创建视图实例,只是使用LoginRequiredView来增强UserInfoView的功能,所以我们不需要LoginRequiredView类依赖于视图类View,对于这种需求,python里面有一种习惯,把这种类定义为Mixin类。

方案三:使用多继承的MRO(方法解析顺序)特征。
login_required装饰器_第3张图片

class LoginRequiredMixin(object):
    @classmethod
    def as_view(self, *args, **kwargs):
        view = super().as_view()
        return login_required(view)

class UserCenterView(LoginRequiredMixin, View):         #  mixin设计模式

    def get(self, request: HttpRequest):
        """打开用户中心页面"""
        context = {
     
            "username": request.user.username,
            "mobile": request.user.mobile,
            "email": request.user.email,
            "email_active": request.user.email_active,
        }
        return render(request, "user_center_info.html", context)

你可能感兴趣的:(#,python进阶知识点,类装饰器,函数装饰器,装饰器)