django练手(十五):实现某些页面不登录不能访问的功能

本节实现的功能是:不登录,访问修改密码的页面,自动跳转到登录界面。登录后,网页自动跳转到修改密码的页面。

一.功能描述及实现思路

这个功能主要依靠django的login_required方法实现。
功能描述和实现思路:

  1. 没有登录的用户访问受保护的视图时,网页自动跳转到登录地址。
  2. 网页跳转时,会以url传参的方式自动在url后加上?next=原访问地址
  3. 登录模板接收url传递过来的参数,并在发起登录请求时以url传参的方式把这个参数传到后端。
  4. 后端视图接收这个参数,登录用户账号。把next参数处理后再返回前端。前端进行跳转动作。
    接下来,我以修改密码的页面为例,实现不登录不能访问的功能。

二.功能实现

  1. 在app-views-app-views.py 文件中引入login_required方法。引入的代码如下:
	from django.contrib.auth.decorators import login_required
  1. 在app-views-app-views.py 文件中找到change_password视图,该视图的作用是修改密码。在该视图上以装饰器的形式使用login_required方法,以达到不登录,就不能访问修改密码页面的效果。具体代码如下:

    @login_required # 以装饰器的形式使用login_required方法
    # 修改密码视图
    def change_password(request):
    	if request.method == 'GET':
    		fields = ChangePassword(request)
    		return render(request, 'app/change_password.html', {'fields': fields})
    	if request.method == 'POST':
    		data = request.POST
    		fields = ChangePassword(request, data)
    		if fields.is_valid():
    			# 获取清洗过的新密码
    			new_password = fields.cleaned_data.get('new_password', '')
    			# 获取当前用户
    			user = request.user
    			# 用新密码修改当前用户的密码
    			user.set_password(new_password)
    			# 保存当前用户
    			user.save()
    			# 当前用户重新登录
    			login(request, user)
    			return JsonResponse({'status': True})
    		else:
    			return JsonResponse({'status': False, 'errors': fields.errors})
    
  2. 在settings.py 文件中指定跳转地址。操作方法如下:
    在settings.py文件末尾加上 LOGIN_URL = '/app/login/',告诉django,如果没有登录的用户访问了,就跳转到'/app/login/'这个地址,这个地址是登录地址。

  3. 修改登录视图的代码,使之能够接收跳转前的地址,并把该地址返回给前端页面,用于登录后的跳转。
    login_required方法跳转时,会自动在网址上加上?next=原访问地址。具体到本项目,
    该地址变成http://127.0.0.1:8000/app/login/?next=/app/changepwd/。接下来,就是修改app-views-app-views.py文件中的login_view视图。
    代码如下:

    def login_view(request):
    	"""
    	功能描述:
    	1、获取网址中携带的next参数的值,这个值是访问登录页面之前访问的地址;
    	2、如果是GET方法访问该视图,返回登录表单。
    	3、如果是POST方法访问该视图,则用LoginForm进行数据验证,如果验证通过,进入登录状态。如果验证不通过,返回错误信息。
    	"""
    	# 获取url中携带的next参数
    	next_url = request.GET.get('next', '') 
    	if request.method == 'POST':
    		data = request.POST
    		fields = LoginForm(request, data)
    		# 登录信息校验成功
    		if fields.is_valid():
    			# 并且next的值不为空
    			if next_url:
    				# 把登录状态的参数status的值设置成True,把next值返回给前端
    				return JsonResponse({"status": True, "next_url": next_url})
    			else:
    				# 把登录状态的参数status的值设置成False,把首页的地址返回给前端
    				return JsonResponse({"status": True, "next_url": '/'})
    		else:
    			return JsonResponse({"status": False, "errors": fields.errors})
    	if request.method == 'GET':
    		fields = LoginForm(request)
    		return render(request, 'app/login.html', {'fields': fields})
    
  4. ajax执行成功后,前端接收next的值,并执行跳转。
    实现思路:
    ①、在用户点击登录按钮后,前端通过ajax的post方法把登录数据发送给后端。同时,url上携带了next参数。
    ②、前端在收到后端的响应后,判断是否登录成功。如果登录成功,就进行跳转。依据后端返回的跳转地址信息,或跳转到登录前页面,或跳转到主页。
    ③、如果没有登录成功,则把登录的错误信息显示在页面上。
    具体代码如下:

    <script>
    		$(document).ready(function () {
    			btnSubmitClick()
    		})
    
    		function btnSubmitClick() {
    			$("#btnSubmit").click(function () {
    				$(".error-msg").empty(); //清除报错信息
    				let data = $("#login_form").serialize(); //获取form表单的数据
    				$.ajax({
    				/*ajax请求发送的地址。与一般的地址不同,这个地址获取了GET请求访问该页面时携带的next参数。在发送ajsx请求时,把next通过url传参的方式传到后台。
                    */
    					url: "{% url 'app:login' %}?next={{ request.GET.next }}",  
    					type: "POST",   //请求的方式是POST请求
    					data: data,     //请求的数据
    					async: true,    //异步方式请求
    					dataType: "json", //返回数据的格式是json
    					// 接下来是请求成功之后执行的函数
    					success: function (res) {
    						if (res.status) {
    							location.href=res.next_url; //如果登录成功,则挑转到next_url代表的地址
    							console.log(res.next_url);
    						} else {                        //请求不成功,把错误信息显示在页面上
    							$.each(res.errors, function (key, value) {
    								$("#id_" + key).next().text(value);
    							})
    						}
    					},
    					// 接下来是请求失败执行的函数
    					errors: function () {
    					   console.log("请求失败");
    					}
    				})
    
    			})
    		}
    	</script>
    
posted @ 2024-01-06 11:05  喜气洋洋白云山  阅读(282)  评论(0编辑  收藏  举报