python-django中的APPEND_SLASH实现方法


Posted in Python onJune 21, 2019

关于django中的APPEND_SLASH

APPEND_SLASH 它是啥?

看变量名大概能知道做什么,就是添加斜线,用路由系统那里。

路由文件,只写了路由关系代码

......
urlpatterns = [
  url(r'^test/$', views.test),
]
......

APPEND_SLASH这个常量默认为True,就是假如你没有添加斜线,他会帮你添加上(总体是这样,具体得看源码怎么写的了)

执行命名行代码启动django项目

python manage.py runserver

目前APPEND_SLASH=True,我们打开浏览器的开发者工具,查看网络请求,输入127.0.0.1:8000/test 这里我是没有加斜线的

python-django中的APPEND_SLASH实现方法

仔细看下网络请求,我们输入127.0.0.1:8000/test,看起来只发送了一次,其实真实发送了两次请求。

我们继续再访问这个url:127.0.0.1:8000/test11,看看请求

python-django中的APPEND_SLASH实现方法

我们也同样访问了一个url,但是这次和上面不同的是,只发送了一次请求。

两次都是发送一个get请求,访问服务器的一个资源。

第一次请求的url为127.0.0.1:8000/test,我们的路由关系中是没有这个url的,对没错,如果访问想要访问到服务器的资源必须为这样的url才行127.0.0.1:8000/test/,虽说这两个url看起来差不多,但其实差很多的。但是第一次请求的url只需在最后加上/,就能访问到资源了,这就是APPEND_SLASH的作用。

第二次请求的url为127.0.0.1:8000/test11,这个地址也不在我们的路由关系中,况且加上了/,也不能访问到资源。所以总共发送了一次,最终返回了404错误。

先大致总结下:APPEND_SLASH=True的情况下,先会根据前端传来的url,先检测这个url能不能访问资源,如果可以访问的话,那么就去执行相应的业务代码,最后返回。如果这个url不能访问到资源的话,会判断这个url最后有没有/,有/的话,则返回404错误;如果没有/的话,便会帮你加上/,生成一个新的url,再去检测这个新的url能不能访问到资源,如果能访问的话,则返回301的状态码,并将这个新的url传到前端,进行重定向操作(这就是我们第一次请求出现的情况),如果这个新的url(帮你加上/的)还是不能访问到资源的话,也会返回404错误(这就是我们第二次请求出现的情况)。这就是对上面出现情况的总结吧(具体流程还得去看源码)

那么APPEND_SLASH=False的情况,就不会帮你加/,你前台传怎样的url,那就用这个url去访问资源,能不能访问还得看你url对不对。

在走到路由层之前,请求会先走到中间件这一层,在这一层就执行了上面分析的逻辑

这一个中间件实现了上面的逻辑 'django.middleware.common.CommonMiddleware',请求来的时候,会走这个中间件的process_request方法,下面来看这个方法写了什么

python-django中的APPEND_SLASH实现方法

看这一句注释:# Check if a slash should be appended,检测是否需要加上斜线

看这个方法should_redirect_with_slash,返回值为bool类型。返回True的情况是,APPEND_SLASH=True,这个url不是以/结尾的,并且这个url添加上了/,能够访问资源的。必须满足这三种情况,返回值为True,其他情况的话返回就是False。

下面贴上should_redirect_with_slash的源码

def should_redirect_with_slash(self, request):
  """
  Return True if settings.APPEND_SLASH is True and appending a slash to
  the request path turns an invalid path into a valid one.
  """
  if settings.APPEND_SLASH and not request.path_info.endswith('/'):
    urlconf = getattr(request, 'urlconf', None)
    return (
      not is_valid_path(request.path_info, urlconf) and
      is_valid_path('%s/' % request.path_info, urlconf)
    )
  return False

就说下 is_valid_path方法有啥作用吧。你可以去看源码具体了解

is_valid_path 检测传进去的url,是否能访问到资源。(说白了就是判断这个url是否存在我们定义的url映射中)

这样的话,上面这段代码就很简单了。首先判断APPEND_SLASH,如果为False的。那么这个方法should_redirect_with_slash直接返回False。如果APPEND_SLASH为True的话,再对请求的url进行判断,request.path_info它的值并不是一个完整的url,而是ip+端口后面的那一部分(也就是例子中的/test),判断它是否以斜线(/)结尾的,如果是的话,那么not request.path_info.endswith('/') 整体就为False,所以if判断后面的表达式就为False,最终返回了False。如果不是以斜线(/)结尾的话,那么if后面的表达式就为True,那么继续执行条件为真的代码块,这个代码块最终返回了一个表达式的结果,这个表达式类型是这样 bool and bool。也就是根据方法is_valid_pathd的返回值进行判断的,如果request.path_info(代码能分析到这里说明它不是以斜线结尾的),首先判断这个值能不能在我们写的路由关系映射中存不存在。存在的话,方法is_valid_path返回真,那么not True就为False,and左边的表达式为False,整体的表达式就为False,所以最终返回的就是False。如果request.path_info的值在路由关系映射中不存在,那么and左边的表达式为True,那就继续看and右边表达式的布尔值。and右边还是调用了方法is_valid_path,只不过传的参数是request.path_info + /,如果在路由映射中存在,那么最终返回True,如果不存在,那么就返回了False了。

should_redirect_with_slash方法分析完毕,继续看源码

# Check if a slash should be appended
if self.should_redirect_with_slash(request):
  path = self.get_full_path_with_slash(request)
else:
  path = request.get_full_path()

后面根据should_redirect_with_slash方法的返回值,做了不同的操作。不严格来说,不管True还是False,最终执行了requests.get_full_path这个方法,只不过传入的参数不同的,最终返回了一个完整的url请求地址。

继续往下看

# Return a redirect if necessary
if redirect_url or path != request.get_full_path():
  redirect_url += path
  return self.response_redirect_class(redirect_url)

如果if后面的表达式为True的话,最终稿返回了一个状态码为301的Httpresponse对象,这个对象里带这一个数据,这个数据就是在原url基础上加上斜线(/)的新url,前端接收到状态码为301的响应,则会继续请求响应中携带的新地址。为False的话,返回默认返回None。

django的中间件会根据每个中间件里的process_request方法或者process_response方法不同的返回值会执行相应的操作,具体操作不说了,不是这个知识点的内容。

那么中间件的process_request返回None的话,则会执行下一个中间件的process_request的方法。如果返回的是HttpResponse对象的话,则不会继续执行下一个中间件的process_request方法,则会执行process_response方法。具体从哪个中间件执行和django的版本有关系,反正是不会执行路由对应的视图代码的代码,会直接返回给前端HttpResoonse对象。

好了,关于APPEND_SLASH的知识总结完毕。APPEND_SLASH它默认为True,如果想要修改的话,需要在settings.py文件中定义这个常量,赋值为False,这样就可以覆盖原django中配置文件里对应的常量了。至于django内部怎么操作的,下次再总结吧

最后还是补个图吧,我把APPEND_SLASH设置为False,访问127.0.0.1:8000/test

python-django中的APPEND_SLASH实现方法

如果你设置了APPEND_SLASH为False,访问上面这个url,还是能访问到页面的话,清理下浏览器的缓存,就可以了

总结

以上所述是小编给大家介绍的python-django中的APPEND_SLASH实现,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
Python实现简单http服务器
Apr 12 Python
Python实现按中文排序的方法示例
Apr 25 Python
python爬取网页内容转换为PDF文件
Jul 28 Python
解决Python3 抓取微信账单信息问题
Jul 19 Python
Python实现微信小程序支付功能
Jul 25 Python
python3 BeautifulSoup模块使用字典的方法抓取a标签内的数据示例
Nov 28 Python
Python爬虫实现模拟点击动态页面
Mar 05 Python
Python实现子类调用父类的初始化实例
Mar 12 Python
python调用私有属性的方法总结
Jul 24 Python
利用python+request通过接口实现人员通行记录上传功能
Jan 13 Python
Django中的JWT身份验证的实现
May 07 Python
Python 如何解决稀疏矩阵运算
May 26 Python
Python2.7版os.path.isdir中文路径返回false的解决方法
Jun 21 #Python
pyqt5与matplotlib的完美结合实例
Jun 21 #Python
django框架防止XSS注入的方法分析
Jun 21 #Python
pyqt5中QThread在使用时出现重复emit的实例
Jun 21 #Python
python发送多人邮件没有展示收件人问题的解决方法
Jun 21 #Python
pyqt5让图片自适应QLabel大小上以及移除已显示的图片方法
Jun 21 #Python
django框架使用orm实现批量更新数据的方法
Jun 21 #Python
You might like
php 中文字符入库或显示乱码问题的解决方法
2010/04/12 PHP
Yii框架实现对数据库的CURD操作示例
2019/09/03 PHP
js类中获取外部函数名的方法与代码
2007/09/12 Javascript
Javascript 面向对象 继承
2010/05/13 Javascript
JavaScript判断一个URL链接是否有效的实现方法
2011/10/08 Javascript
Jquery实现网页跳转或用命令打开指定网页的解决方法
2013/07/09 Javascript
从数组中随机取x条不重复数据的JS代码
2013/12/24 Javascript
js调试工具Console命令详解
2014/10/21 Javascript
jQuery实现在列表的首行添加数据
2015/05/19 Javascript
js操作数据库实现注册和登陆的简单实例
2016/05/26 Javascript
vue分页组件table-pagebar使用实例解析
2020/11/15 Javascript
基于JS递归函数细化认识及实用实例(推荐)
2017/08/07 Javascript
Vue中render方法的使用详解
2018/01/26 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
2018/08/22 Javascript
Bootstrap4 gulp 配置详解
2019/01/06 Javascript
Vue和React组件之间的传值方式详解
2019/01/31 Javascript
koa-router路由参数和前端路由的结合详解
2019/05/19 Javascript
p5.js临摹动态图形的方法
2019/10/23 Javascript
原生js实现随机点名功能
2019/11/05 Javascript
vue excel上传预览和table内容下载到excel文件中
2019/12/10 Javascript
JS三级联动代码格式实例详解
2019/12/30 Javascript
[01:06:54]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第一场 1月24日
2021/03/11 DOTA
python 简单的绘图工具turtle使用详解
2017/06/21 Python
Python tkinter模块中类继承的三种方式分析
2017/08/08 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
Python Gitlab Api 使用方法
2019/08/28 Python
Python创建数字列表的示例
2019/11/28 Python
python多进程 主进程和子进程间共享和不共享全局变量实例
2020/04/25 Python
基于canvas的骨骼动画的示例代码
2018/06/12 HTML / CSS
什么是Deployment descriptors;都有什么类型的部署描述符
2015/07/28 面试题
美术专业个人自我评价
2014/01/18 职场文书
活动总结格式
2014/08/30 职场文书
小学生安全教育主题班会
2015/08/12 职场文书
TV动画《间谍过家家》公开PV
2022/03/20 日漫
win11高清晰音频管理器在哪里?win11找不到高清晰音频管理器解决办法
2022/04/08 数码科技
HTML5之高度塌陷问题的解决
2022/06/01 HTML / CSS