urls路由
上一节用到了urls,这里用尽量简单的语言讲一下。网址url相当于一个地址,用这个去找某个公司里的某个人。
这是一个工程目录,里面有两个应用,相当于一个大院里面有两家公司,那么工程目录下的urls就相当于大院的传达室,拿着地址找人必须先问传达室。
helapp这个公司比较大,所以设立的一个前台接待,只要是来传达室找helapp这个公司的,直接领到这个前台去问接下来的路。
daka这个公司比较小,没有自己的前台,那么就由大院传达室直接领去办公室(views)并且找到里面该找的人(方法)。
要从大院传达室领到公司前台,就用include()方法,领到下一级路由urls,并把匹配剩下的url传过去。比如上图中匹配完了‘hello’,交给下一级路由时‘hello’和其前面的url就都不管了,下一级url只处理url后面剩下的部分。
公司内的前台接待会根据地址找到对应的人,应用内的urls会根据url找到对应的方法。公司前台找人,跟传达室帮没有前台的公司找人,方式是类似的。
如果我们想在url里写一些动态的变量信息传递给后端,Django是不喜欢用GET方法的url参数的,通常Django使用正则表达式来解析url,提取出其中的变量并传递给方法。
简单的正则表达式
尖括号为标志,表达式写成<变量类型:变量名>
的形式,这种正则不需要import额外的方法。
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('/', views.detail, name='detail'),
# ex: /polls/5/results/
path('/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('/vote/', views.vote, name='vote'),
]
变量名所指的变量就作为后面的方法的一个参数传递过去,在views中用形参接收:
def detail(request, id):
return HttpResponse("You're looking at question %s." % id)
def results(request, id):
response = "You're looking at the results of question %s."
return HttpResponse(response % id)
def vote(request, id):
return HttpResponse("You're voting on question %s." % id)
转换格式类型 | 说明 |
---|---|
Str | 匹配除分隔符(/)外的非空字符,默认类型 |
Int | 匹配0和正整数 |
Slug | 匹配字母、数字、横杠、下划线组成的字符串,str的子集 |
Uuid | 匹配格式化的UUID,如075194d3-6885-417e-a8a8-6c931e272f00 |
path | 匹配任何非空字符串,包括路径分隔符,是全集 |
re正则表达式
使用re_path()
代替path()
,并在字符串的引号前加r
。
Python正则表达式前的 r 表示原生字符串(rawstring),该字符串声明了引号中的内容表示该内容的原始含义,避免了多次转义造成的反斜杠困扰。大概意思就是加了r
的不用再考虑字符串中标点的转义,程序会自动帮忙转义。知乎-python正则表达式加了r之后\w,\s,.这些有含义的字符串和没有加r的区别?
但是笔者发现加了r
可以激活我安装的正则表达式可视化插件,所以还是加上r
。
提示:
- 使用GET请求获得参数时,斜杠(/)、句点(.)一般不可取到字符串参数内。一串“/”隔开的url取参数需要每个单独取。如:
- django2.0中,使用正则表达式进行路由的话需要使用re_path()
from django.urls import path, re_path
from . import views
urlpatterns = [
re_path('^hello/$', views.hello),
re_path('^hello/(?P[0-9]+)/', views.hello),
]
要点:
-
匹配头用尖号^,前部固定,后部自由:
-
匹配尾用$,后部固定,前部自由:
-
匹配变量参数:
字符串:(?P\w+),+表示多个字符
数字:(?P\d+),+表示多个数字
类型、个数匹配:(?P[0-9]{4}) //4个0-9的数字
尖括号内是变量名,会作为views中的方法的参数传给views
附:正则表达式用法小结
#正则表达式:
# 元字符: \w \d \s \n \t \W \S \D \b ^ 尖角号 $ . [] [^] () |
# [0-9] \d
# [1-9]
# [\da-zA-Z]
#. :匹配除换行符"\n"以外的任意字符
#\ :转义字符,使后一个字符改变原来的意思.如果字符串中有字符*需要匹配,可以使用\*或者字符集{*}
#[...]:字符集,对应的位置可以是字符集中任意字符.字符集中的字符可以逐个列出,也可以给出范围,如[abc]
#或者是[a-c],第一个字符如果是^,则表示取反,如[^abc]表示不是abc的其他字符.所有的特殊字符在字符集中
# 都失去其原有的特殊含义.在字符集中如果要使用].-或^,可以在前面加上反斜杠,或者把],-放在第一个字符,把^
#放在非第一个字符
#\d 数字:[0-9]
#\D 非数字:[^\d]
#\s 空白字符:[<空格> \t\r\n\f\v]
#\S 非空白字符:[^\s]
#\w 单词字符:[0-9a-zA-Z_]包括了数字字母下划线
#\W 非单词字符:[^\w]
#量词 : {n} {n,} {n,m} * ? +
#* :匹配前一个字符0或无限次 abc*
#+:匹配前一个字符1次货无限次. abc+
#?:匹配前一个字符0次或1次. abc?
#{n}:匹配前一个字符n次 ab{2}c 匹配字符:abbc
#{n,}:至少匹配n次,至无限次
#{n,m}:匹配前一个字符n到m次 ab{1,2}c 匹配字符abc,abbc
#*?, +?, ?? {m,n}?,使* + ? {m,n}变成非贪婪模式
#边界匹配:
#^ :匹配字符串开头,
# 在多行模式中匹配每一行的开头. ^abc 匹配字符abc
#$ :匹配字符串末尾,
# 在多行模式中匹配每一行的末尾. abc$ 匹配字符abc
#\A 仅匹配字符串开头 \Aabc 匹配字符abc
#\Z 仅匹配字符串末尾 abc\Z 匹配字符abc
#\b 匹配\w和\W之间 a\b!bc a!bc
# |:|代表左右表达式任意匹配一个.它总是先尝试匹配左边的表达式
#一旦左边的表达式成功匹配则跳过右边的表达式
#如果|没有被包括在()中,则它的范围是整个正则表达式 abc|def
#(...) :被括起来的表达式将作为分组,从表达式左边开始每遇到
#一个分组的左括号"(",编号+1.另外,分组表达式作为一个整体,可以接数量词.
#表达式中的|仅在该组有效.
#(?P...):分组,除了原有的编号外再指定一个额外的别名.
#\:引用编号为的分组匹配到的字符串. (\d)abc\1
#(?P = name):引用别名为的分组匹配到的字符串
#转义符:
# python str : '\'
# 正则表达式中的'\'到了python中都会变成'\\'
# r'\w' 在python当中\不转义了,在Python中就是一个普通的'\',但是在正则表达式中它还是表示一个转义符
# 贪婪匹配/惰性匹配 :
# .*x 贪婪 匹配任意内容最多次,直到最后一个X停止 回溯算法
# .*?X 惰性 匹配任意内容最少次,遇到第一个X就停止
# re模块
# findall 匹配所有 列表
# search 匹配第一个 变量.group(),没匹配到返回None
# match 从头开始匹配第一个
# split sub subn
# finditer compile
# finditer 返回一个迭代器,所有匹配到的内容需要迭代取到,迭代取到的每一个结果都需要group取具体值
# -- 节省内存空间
# compile 编译,先把一个正则表达式编译,编译之后,在之后多次使用的过程不用重新编译
# -- 节省时间 提高效率
# 分组:()
# 1.给不止一个字符的整体做量词约束的时候 www(\.[\w]+)+ www.baidu.com
# 2.优先显示,当要匹配的内容和不想匹配的内容混在一起的时候,
# 就匹配出所有内容,但是对实际需要的内容进行分组
# 3.分组和re模块中的方法 :
# findall : 分组优先显示 取消(?:正则)
# search :
# 可以通过.group(index)来取分组中的内容
# 可以通过.group(name)来取分组中的内容
# 正则 (?P正则)
# 使用这个分组 ?P=name
# split : 会保留分组内的内容到切割的结果中
-
Django——路由分配设置 re_path正则匹配 include总路由 url传参 name使用 模板渲染render方法 模板渲染方法[1] ↩
-
URL调度器[2] ↩
-
关于正则,关于模块,关于深情的python~[3] ↩