django限制匿名用户访问及重定向的方法实例


Posted in Python onFebruary 07, 2018

前言

大家应该都遇到过,在某些页面中,我们不希望匿名用户能够访问,例如个人页面等,这种页面只允许已经登录的用户去访问,在django中,我们也有比较多的方式去实现。

最简单的,我们在viewz中去判断用户is_authenticated,但这种方法也相对比较笨拙,最理想的的我们当然不希望这个请求能够进入到我们view,在这之前就能够返回一个相关的response,而django其实已经给我们封装好了相关的函数与类。下面话不多说了,来一起看看详细的介绍吧。

基于fbv模式的login_required装饰器

def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, 
   login_url=None):
 # 实际上这个方法也是调用is_authenticated去判断
 pass

使用方法也很简单:

# fbv模式
from django.contrib.auth.decorators import login_required
@login_required 
def user_info_view(request):
 # 用户个人界面
 pass

那么,我们希望如果是匿名用户在访问这个界面后能够重定向到login界面,我们可以设置相关参数,login_required装饰器会默认去读取settings.LOGIN_URL,并重定向到这个页面,如果希望更为灵活,那么我们也可以给装饰器传相关参数。

# fbv模式
@login_required(login_url='/login/', redirect_field_name='next')
def user_info_view(request):
 # 用户个人界面
 pass

login_url就是匿名用户访问后重定向的url,一般都是login的页面

redirect_field_name是一个get请求的参数

假设当前页面会/user/info/

那么重定向的url为: /login/?next=/user/info/

这个参数可以用于登陆后直接跳转回这个页面,后面还会具体介绍!

基于cbv的LoginRequiredMixin类

博主一般常用都是cbv模式,在这个模式下,我们会重写get和post方法,理论上可以用login_required装饰器去装饰这两个方法

# cbv模式
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class UserInfoView(View):
 @method_decorator(login_required(login_url='/login/', redirect_field_name='next'))
 def get(self, request):
 # 获取用户个人界面
  pass

login_required是函数装饰器,method_decorator可以将函数装饰器转化成方法装饰器。如果这里还有post请求,那这样的代码我们还要在写一遍,这样就显得有点冗余,我们既然用了类来实现,当然通过类的优势来实现!继承LoginRequiredMixin!

from django.contrib.auth.mixins import LoginRequiredMixin
class UserInfoView(LoginRequiredMixin, View):
 def get(self, request):
 # 获取用户个人界面
  pass

那么,LoginRequiredMixin是怎么去实现的呢?

看看源代码

class LoginRequiredMixin(AccessMixin):
 def dispatch(self, request, *args, **kwargs):
  if not request.user.is_authenticated():
   return self.handle_no_permission()
  return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

其实它重写了dispatch方法,因为我们还继承了view,其实它重写的view中的dispatch函数,如果知道view的逻辑,你就知道为什么能够这样实现了!

当我们在url中,调用你的view类,如UserInfoView.as_view()方法,它会去调用dispatch() ,这个方法起到一个分配器的作用,如果get请求,那么他就调用get方法,如果是post请求,那么就调用post方法。那么,在dispatch中去判断用户是否登录,当然可以起到这个作用。

那既然只是重写dispatch,我们也可以自己实现!

# 自定义LoginRequiredMixin
class LoginRequiredMixin(object):

 @method_decorator(login_required(login_url='/login/', redirect_field_name='next'))
 def dispatch(self, request, *args, **kwargs):
  return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

当然,有没有必要自己实现,那就看各自的需求啦~

重定向与跳转

(login_url='/login/', redirect_field_name='next')

这两个参数提供了一个重定向与跳转的url给我们,当匿名用户登录需要登录的页面时,就会跳转到login_url,这个get请求还带着redirect_field_name参数,值是'next'。

假如他访问的是个人页面,那么跳转到

http://127.0.0.1/login/?next=/user/info/

我们可以通过这个参数,在登录后直接跳转到个人页面。

class LoginView(View):
 """
 用户登录逻辑
 """
 def get(self, request):
  # 获取到next参数,渲染到template中,在form表单添加一个hidden类型的元素
  next = request.GET.get('next', '')
  return render(request, "login.html", {'next': next})

 def post(self, request):
  login_form = LoginForm(request.POST)
  if login_form.is_valid():
   user_name = request.POST.get("username", "")
   pass_word = request.POST.get("password", "")
   next = request.POST.get('next', '')
   user = authenticate(username=user_name, password=pass_word)
   if user is not None:
    if user.is_active:
     login(request, user)
     if next:
     # 如果next存在,直接跳转到指定页面
      return HttpResponseRedirect(next)
     # 不存在跳转到index界面
     return HttpResponseRedirect(reverse('index'))
    else:
     return render(request, "login.html", {"msg": "用户未激活"})
   else:
     return render(request, "login.html", {"msg": "用户名或密码错误"})
  else:
   return render(request, "login.html", {"login_form": login_form})
# login.html template form中添加
<input name="next" type="hidden" value="{{ next }}"/>

普通页面的登录跳转问题

如果普通页面也想要实现登录后跳转回原来的页面,十分简单,在request中有个path参数,它表示当前页面,我们只需要在跳转到login界面把这个参数带上即可

# template
<a class="loginbtn" href="/login/?next={{ request.path }}" rel="external nofollow" >登录</a>
<a class='logoutbtn' href="/logout/?next={{ request.path }}" rel="external nofollow" 退出</a>
<a class='registerbtn' href="/register/?next={{ request.path }}" rel="external nofollow" 注册</a>

login的实现逻辑同上面的一样,其实logout和注册界面的实现逻辑也是一样的。

# logout
class LogoutView(View):
 def get(self, request):
  next = request.GET.get('next', '')
  logout(request)
  try:
   return HttpResponseRedirect(next)
  except:
   return HttpResponseRedirect(reverse('index'))

后言

本篇重点在于@login_required装饰器的使用,以及LoginReqiredMixin类的使用和自定义,最后实现登录的重定向以及跳转!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
在Python中编写数据库模块的教程
Apr 29 Python
CentOS安装pillow报错的解决方法
Jan 27 Python
python2 与python3的print区别小结
Jan 16 Python
详解Numpy中的广播原则/机制
Sep 20 Python
python3 property装饰器实现原理与用法示例
May 15 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
Jul 11 Python
Python pandas实现excel工作表合并功能详解
Aug 29 Python
Python @property原理解析和用法实例
Feb 11 Python
详解Python 函数参数的拆解
Sep 02 Python
python装饰器三种装饰模式的简单分析
Sep 04 Python
Python3.9.1中使用split()的处理方法(推荐)
Feb 07 Python
总结几个非常实用的Python库
Jun 26 Python
Python用 KNN 进行验证码识别的实现方法
Feb 06 #Python
Python实现的径向基(RBF)神经网络示例
Feb 06 #Python
python实现淘宝秒杀聚划算抢购自动提醒源码
Jun 23 #Python
初探TensorFLow从文件读取图片的四种方式
Feb 06 #Python
用十张图详解TensorFlow数据读取机制(附代码)
Feb 06 #Python
Python实现matplotlib显示中文的方法详解
Feb 06 #Python
Python实现自动上京东抢手机
Feb 06 #Python
You might like
PHP中list方法用法示例
2016/12/01 PHP
php简单处理XML数据的方法示例
2017/05/19 PHP
PHP格式化显示时间date()函数代码
2018/10/03 PHP
PHP命名空间与自动加载机制的基础介绍
2019/08/25 PHP
Laravel 微信小程序后端搭建步骤详解
2019/11/26 PHP
JavaScript实用技巧(一)
2010/08/16 Javascript
基于jquery的仿百度的鼠标移入图片抖动效果
2010/09/17 Javascript
使用jquery动态加载javascript以减少服务器压力
2012/10/29 Javascript
JavaScript闭包实例详解
2016/06/03 Javascript
AngularJS入门教程之XHR和依赖注入详解
2016/08/18 Javascript
AngularJS通过$http和服务器通信详解
2016/09/21 Javascript
基于Bootstrap和jQuery构建前端分页工具实例代码
2016/11/23 Javascript
彻底学会Angular.js中的transclusion
2017/03/12 Javascript
JavaScript之生成器_动力节点Java学院整理
2017/06/30 Javascript
如何使用JS在HTML中自定义字符串格式化
2017/07/20 Javascript
AngularJS实现的鼠标拖动画矩形框示例【可兼容IE8】
2019/05/17 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
微信小程序地图实现展示线路
2020/07/29 Javascript
python网络编程学习笔记(九):数据库客户端 DB-API
2014/06/09 Python
python基于queue和threading实现多线程下载实例
2014/10/08 Python
50行Python代码实现人脸检测功能
2018/01/23 Python
python2.7实现FTP文件下载功能
2018/04/15 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
2018/04/17 Python
Python单元测试实例详解
2018/05/25 Python
在python中以相同顺序shuffle两个list的方法
2018/12/13 Python
Python图像处理之gif动态图的解析与合成操作详解
2018/12/30 Python
python实现生成字符串大小写字母和数字的各种组合
2019/01/01 Python
Python 实现交换矩阵的行示例
2019/06/26 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
2020/03/20 Python
英国舒适型鞋履品牌:FitFlop
2017/05/17 全球购物
心得体会范文
2014/01/04 职场文书
护士自我鉴定怎么写
2014/02/07 职场文书
《影子》教学反思
2014/02/21 职场文书
岗位说明书怎么写
2014/07/30 职场文书
MySQL去除密码登录告警的方法
2022/04/20 MySQL
Spring Boot接口定义和全局异常统一处理
2022/04/20 Java/Android