django路由层(一)
Django的路由系统
URL配置(URLconf)就像Django所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表。
我们就是以这种方式告诉Django,遇到哪个URL的时候,要对应执行哪个函数。
URLconf配置
基本格式:
示例:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test', views.test),
url(r'^testadd',views.testadd)
]
django项目目录中, 路由层就是urls.py这个文件来进行控制
urlpatterns这个变量定义的一个列表,列表中通过url这个函数进行路由分发到视图层
url函数中是通过正则匹配浏览器中输入的网址中的路径中的最后一位进行正则匹配 (匹配 admin,test,testadd)
参数说明:
- 正则表达式:一个正则表达式字符串
- views视图:一个可调用对象,通常为一个视图函数
- 参数:可选的要传递给视图函数的默认参数(字典形式)
- 别名:一个可选的name参数
注意事项
- urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
- 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的'r' 是可选的但是建议加上
- Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。
代码验证
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('test', views.test),
url('testadd',views.testadd)
]
views.py
def test(request):
return HttpResponse('test')
def testadd(request):
return HttpResponse('testadd')
浏览器测试
输入 http://127.0.0.1:8000/test/, 返回test
输入 http://127.0.0.1:8000/testadd/, 也是返回test
需求分析
上面的结果并不是我们想要的,我们希望的结果是:
而从上面的结果验证可知道:
路由文件中url函数后面跟着的第一个参数是正则表达式,匹配规则按照从上往下一次匹配,匹配到一个之后立即匹配。
当我们输入 http://127.0.0.1:8000/testadd/, url('test', views.test),这一个元素先匹配到了testadd,就相当于re.findall('test','testall'),这样就匹配到了test这个字符串,对应的会执行视图层中的test函数,所以最后返回来test
>>> import re
>>> re.findall('test','testall')
['test']
需求1 输入不同的url路径返回不同的字符串
解决方案1:
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('test/', views.test),
url('testadd/',views.testadd)
]
浏览器测试
输入 http://127.0.0.1:8000/test/, 返回test
但是这里有个问题:
当我们输入 http://127.0.0.1:8000/test/sdsddsdsfsdf, 正常返回test
当我们输入 http://127.0.0.1:8000/dsdsdsdssdtest/sdsddsdsfsdf, 正常返回test
当我们输入 http://127.0.0.1:8000/testadd/sdsddsdsfsdf, 正常返回testadd
当我们输入 http://127.0.0.1:8000/dsdsdsdssdtestadd/sdsddsdsfsdf, 正常返回testadd
解决方案2:
因为路由匹配是正则匹配的规律,所以使用正则表达式进行精准匹配
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url('^test/$', views.test),
url('^testadd/$',views.testadd)
]
需求2 希望主页也有内容, 用户输错网址给个提示信息
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.home),
url('^test/$', views.test),
url('^testadd/$',views.testadd),
url(r'', views.error),
]
views.py
from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def home(request):
return HttpResponse('这是首页')
def error(request):
return HttpResponse('你输了什么鬼')
def test(request):
return HttpResponse('test')
def testadd(request):
return HttpResponse('testadd')
浏览器测试
路由分发
url('正则表达式','视图函数内存地址')
django每一个app下面都可以有自己的url.py 路由层,templates文件夹,static文件夹
项目名下urls.py(总路由)不再做路由与视图函数的匹配关系而是做路由的分发
from django.conf.urls import include
# 路由分发 注意路由分发总路由千万不要$结尾
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))
# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系即可
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^index/',views.index)
]
案例
urls.py
from django.conf.urls import url, include
urlpatterns = [
url(r'app01/',include('app01.urls')),
url(r'app02/',include('app02.urls')),
]
app01.urls
from django.conf.urls import url
from app01 import views
urlpatterns = [
url('^index/',views.index)
]
app01.views
def index1(request):
return HttpResponse('index1')
app02.urls
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request):
return HttpResponse('index2')
app02.views
def index2(request):
return HttpResponse('index2')
分组
无名分组
将加括号的正则表达式匹配到的内容当做位置参数自动传递给对应的视图函数
默认匹配到后,默认把request一定会传给视图函数,因为url函数是采取正则匹配,正则匹配中如果匹配到分组的内容,则输出分组,所以我们可以通过正则表达式分组的特点将匹配到的分组的内容传递给视图函数,但是视图函数需要增加一个形参来接收正则匹配匹配到的分组的内容
>>> re.findall('test/([0-9]+)','test/2018')
['2018']
>>> re.findall('test/([0-9]+)','test/20183333333')
['20183333333']
url(r'^test/(\d+)/', views.test), # 匹配一个或多个数字
def test(request,xxx):
print(xxx)
return HttpResponse('test')
url.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
# url(r'^test/[0-9]{4}/', views.test),
url(r'^test/(\d+)/', views.test), # 匹配一个或多个数字
url(r'^testadd/', views.testadd),
# url(r'',views.error)
]
views.py
from django.shortcuts import render,HttpResponse,redirect
def test(request):
return HttpResponse('test')
def testadd(request):
return HttpResponse('testadd')
def home(request):
return HttpResponse('首页')
def error(request):
return HttpResponse('广告位招租')
显示的页面
修改代码
views.py
from django.shortcuts import render,HttpResponse,redirect
def test(request,xxx):
print(xxx)
return HttpResponse('test')
有名分组
将加括号的正则表达式的内容当做关键字参数自动传递给响应的视图函数
正则表达式复习
>>> a=re.match('test/(?P<name>[0-9]+)','test/123')
>>> a.group('name')
'123'
>>> a=re.match('test/(?P<name>\d+)','test/123')
>>> a.group('name')
'123'
使用
url(r'^test/(?P
\d+)/', views.test)
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.home),
# url(r'^test/[0-9]{4}/', views.test),
# 无名分组
# url(r'^test/(\d+)/', views.test), # 匹配一个或多个数字
# 有名分组
url(r'^test/(?P<year>\d+)/', views.test), # 匹配一个或多个数字,并可以通过year取值
url(r'^testadd/', views.testadd),
# url(r'',views.error)
views.py
def test(request,year): # 这里的形参year必须和路由层中正则匹配的名字是一样的
print(year)
return HttpResponse('test')
注意
有名分组和无名分组不能混着用,但是多个有名分组和多个无名分组可以连用
代码验证
同时使用无名分组和有名分组, 报错
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
# 测试 同时使用无名分组和有名分组
url(r'test/(?P<year>\d+)/[0-9](\d+)',views.test),
]
views.py
def test(request,xxx,year):
print(year)
return HttpResponse('test')
使用多个有名分组
urls.py
urlpatterns = [
# 测试 使用多个无名分组
url(r'test/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)',views.test),
]
views.py
from django.shortcuts import render,HttpResponse,redirect
def test(request,month,day,year):
print(year)
return HttpResponse('test')