python-django中的APPEND_SLASH实现
关于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
这里我是没有加斜线的
仔细看下网络请求,我们输入127.0.0.1:8000/test,看起来只发送了一次,其实真实发送了两次请求。
我们继续再访问这个url:127.0.0.1:8000/test11
,看看请求
我们也同样访问了一个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
方法,下面来看这个方法写了什么
看这一句注释:# 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_path
d的返回值进行判断的,如果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
如果你设置了APPEND_SLASH为False,访问上面这个url,还是能访问到页面的话,清理下浏览器的缓存,就可以了
python-django中的APPEND_SLASH实现的更多相关文章
- Python Django中QQ邮箱授权码问题
Python Django中QQ邮箱授权码问题 系统及软件版本如下: Ubuntu Kylin 16.04 Python 3.5.1 Django 1.9.7 PyCharm Community Ed ...
- RSA算法在Python Django中的简单应用
说明 RSA算法是当今使用最广泛,安全度最高的加密算法. • RSA算法的安全性理论基础 [引]根据百科介绍,对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难, ...
- Python Django 中的STATIC_URL 设置和使用解析
使用Django静态设置时,遇到很多问题,经过艰苦的Baidu, stack overflow, Django原档阅读,终于把静态图片给搞出来了.特记录下来. 关键的概念:Django中,静态资源的存 ...
- python Django中的cookie和session
目录 Cookie 1.1获取Cookie 1.2设置Cookie Session 1.数据库Session 2.缓存Session 3.文件Session 4.缓存+数据库Session Cooki ...
- python django中使用sqlite3数据库 存储二进制数据ByteArray
在python中使用sqlite3数据库存储二进制流数据ByteArray,在django使用sqlite3数据库时,有时候也要注意最好使用二进制流ByteArray插入字符串. 使用ByteArra ...
- python django中的orm外键级联删除
今天添加了一个路由表,路由表做外键,然后添加了几个组,路由表为组的外键,当我使用删除功能对路由表进行删除时,竞然将我的组也相当的删除了:尽管这是测试,但放到生产环境中还是会发生意外的:这个问题要解决: ...
- Python Django中一些少用却很实用的orm查询方法
一.使用Q对象进行限制条件之间 "或" 连接查询 from django.db.models import Q from django.contrib.auth.models im ...
- python django中restful框架的使用
在使用django进行前后台分离开发时通常会搭配django-rest-framework框架创建RESTful风格的接口API.框架介绍及版本要求可参考官方地址:https://www.django ...
- Python Django CMDB项目实战之-2创建APP、建模(models.py)、数据库同步、高级URL、前端页面展示数据库中数据
基于之前的项目代码来编写 Python Django CMDB项目实战之-1如何开启一个Django-并设置base页index页文章页面 现在我们修改一个文章列表是从数据库中获取数据, 下面我们就需 ...
随机推荐
- Mysql 之根据经纬度按距离排序
一.方式一 st_distance 计算的结果单位是度,需要乘111195(地球半径6371000*PI/180)是将值转化为米. SELECT *, (st_distance(point(lng,l ...
- D3.js的v5版本入门教程(第五章)—— 选择、插入、删除元素
D3.js的v5版本入门教程(第五章) 1.选择元素 现在我们已经知道,d3.js中选择元素的函数有select()和selectAll(),下面来详细讲解一下 假设我们的<body>中有 ...
- 坑爹微信之读取PKCS12流时出现的java.io.IOException: DerInputStream.getLength
背景 微信退款接口需要使用到证书,我参考微信的官方Demo进行,部分代码如下: char[] password = config.getMchID().toCharArray(); InputStre ...
- 把pdf的内容转化为txt文件
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.util.PDFTextStripper; import j ...
- #C++初学记录(动态规划 被3整除的子序列)
原题:牛客网 动态规划dynamic programming 的入门级题目 题目描述 : 给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除 答案对1e9+7取模 输入描述: 输入一 ...
- linux学习(4):linux常用命令(50个)
linux常用命令(50个) 1. find 基本语法参数如下: find [PATH] [option] [action] # 与时间有关的参数: -mtime n : n为数字,意思为在n天之前的 ...
- 【err】tensorflow.python.framework.errors_impl.OutOfRangeError: RandomShuffleQueue
problem Traceback (most recent call last): File , in _do_call return fn(*args) File , in _run_fn opt ...
- LeetCode 131. 分割回文串(Palindrome Partitioning)
131. 分割回文串 131. Palindrome Partitioning 题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. LeetC ...
- win10无法安装软件解决
https://www.windowscentral.com/how-fix-network-resource-unavailable-install-error-windows-10
- 20191213-RF中报告打不开提示Opening Robot Framework report failed
配置好Jenkins的RF框架后跑了一次autotest发现哦豁report打不开,网上找了一堆方法都是只能临时解决,重启后又失效了.现在给出临时解决方案和永久解决方案 首先错误信息如下: 临时解决 ...