三、Django的urls
Django的urls相关
一、url配置
无名分组
urls.py:
url(r'^books/(\d{4})/', views.books),
views.py:
def books(request,year): # 必须给一个参数
print(year)
return HttpResponse(year)
比如用户输入网址:127.0.0.1:8000/books/2000,则返回页面打印的就是2000;
输入127.0.0.1:8000/books/2018,则返回页面打印的就是2018;
效果:
位置参数(按顺序传参)
urls:
url(r'^books/(\d{4})/', views.year_books), #匹配年份的
http://127.0.0.1:8000/books/2001/
url(r'^books/(\d{4})/(\d{1,2})/', views.year_month_books), #匹配年份和月份的
http://127.0.0.1:8000/books/2001/12/
视图 views文件:
def year_month_books(request,year,month): #位置参数,第一个参数接收的就是无名分组路径中匹配到的第一个分组的数据,第二个参数接收的就是无名分组路径中匹配到的第二个分组的数据
print(year,month)
# return render(request,'books.html')
return HttpResponse(year+month)
假如有这样一个需求:用户输入127.0.0.1:8000/books/2001,则只匹配年份2001;输入127.0.0.1:8000/books/2001/12,则匹配年份和月份
urls.py:
urlpatterns = [
url(r'^books/(\d{4})/$', views.year_books), # 在末尾加$,严格匹配,否则无论用户只输入了年份,还是输年份和月份,都只匹配这个,显示年份
url(r'^books/(\d{4})/(\d{1,2})/', views.year_month_books)
views.py:
def year_books(request,year):
print(year)
return HttpResponse(year)
def year_month_books(request,year,month):
print(year)
print(month)
return HttpResponse(year+month)
注意事项:
- urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
- 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
- 不需要添加一个前导的反斜杠(也就是写在正则最前面的那个/),因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的'r' 是可选的,表示转义,但是建议加上。
- ^articles$ 以什么结尾,以什么开头,严格限制路径
补充:
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
# 写在settings文件里
APPEND_SLASH=True
# 默认是True,比如输入127.0.0.1:8000/books/2001,2001后面没有加/,会返回一个3xx的状态码,然后给2001后面拼一个/,然后再去请求;
APPEND_SLASH=False
# 设置了False,此时再输入127.0.0.1:8000/books/2001就访问不到了,必须在2001后面加/才可以访问
有名分组
urls:
url(r'^books/(?P<year>\d{4})/(?P<month>\d{1,2})/', views.year_month_books),
views:
def year_month_books(request,month,year): #形参名称要和url中的分组名对应好,参数位置就没有要求了
print(year,month)
return HttpResponse(year+month)
默认值
# urls.py中
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
# views.py中,可以为num指定默认值
def page(request, num="1"):
pass
比如:
urls:
urlpatterns = [
url(r'^books/$', views.books),
url(r'^books/(?P<num>\d{4})/',views.books),
]
views:
def books(request,num='10'):
print(num)
return HttpResponse(num)
效果:
当输入网址127.0.0.1:8000/books/,走默认值,页面显示默认值10:
当输入网址127.0.0.1:8000/books/2002/,被下面的正则匹配到,显示后面的数,比如2002:
二、url路由分发——include
views和models文件都放在了app的应用里面,而urls.py这个文件放在了项目的文件里,说明所有的app都在使用这个urls.py文件,当项目的应用有很多个,那urls文件里面要写很多的对应关系,所有的app的url都写在这一个文件中,耦合度太高,多以Django提供了一个分发接口——include
也就是在每个app应用文件里都写一个属于自己的urls.py文件,然后在项目文件的urls.py文件用include分发借口
例子:
因为pycharm新建时,只能建立一个应用app01,再建立一个应用app02方法:
-
先在settings配置文件配置下app02(app01在建立项目时候自动配置了)
INSTALLED_APPS = [
......
'app01.apps.App01Config',
'app02.apps.App02Config',
] -
应用 app01 下建立urls.py文件,写本应用对应的路径关系
from django.conf.urls import url
from app01 import viewsurlpatterns = [ url(r'^index/', views.index), ]
应用 app01 下的视图 views.py
from django.shortcuts import render,HttpResponse
# Create your views here.def index(request): return HttpResponse('应用界面01')
-
应用 app02 下建立urls.py文件
from django.conf.urls import url
from app02 import viewsurlpatterns = [ url(r'^home/',views.home ), ]
应用 app02 下的视图 views.py
from django.shortcuts import render,HttpResponse
# Create your views here.def home(request): return HttpResponse('应用界面02')
-
主项目中的urls,要用 include 分发接口
from django.conf.urls import url,include # 记得要导入include
from django.contrib import adminurlpatterns = [ url(r'^app01/', include('app01.urls')), # 相当于:http://127.0.0.1:8000/app01/asdsfdfeas.... url(r'^app02/', include('app02.urls')), # 相当于:http://127.0.0.1:8000/app02/..... ] # 注意点:想用include分发路径,千万不要用到 $ ,否则无法匹配.比如:url(r'^app01/$', include('app01.urls'))
-
此时在网址输入 127.0.0.1:8000/app01/index/,先走主项目的urls,匹配到127.0.0.1:8000/app01/,把剩余的路径 index/ 通过include的功能传给app01里面的urls,匹配index/,得到结果
同理,输入 127.0.0.1:8000/app02/home/,也能拿到对应的结果
在此基础上,有这样一个需求:给整个项目做一个首页,每个应用也都做一个首页
-
再建立一个应用app03,专门做整个项目的首页
主项目的urls:
from django.conf.urls import url,include
from app03 import viewsurlpatterns = [ url(r'^$', views.base), # 匹配空内容,就是输入ip和端口后什么也没输入 # 注意:别忘记写^$ url(r'^app01/', include('app01.urls')), # http://127.0.0.1:8000/app01/asdsfdfeas.... url(r'^app02/', include('app02.urls')), # http://127.0.0.1:8000/app02/..... ]
app03 下的 views:
from django.shortcuts import renderdef base(request): return render(request,'base.html')
base.html 放在 模板 templates 文件夹中
欢迎来到首页
-
制作app01的首页:
app01 下的urls:
from django.conf.urls import url
from app01 import viewsurlpatterns = [ url(r'^$',views.firstbase ), url(r'^index/', views.index), ]
app01 下的views:
from django.shortcuts import render,HttpResponsedef index(request): return HttpResponse('应用界面01') def firstbase(request): return render(request,'app01base.html')
app01base.html 放在 模板 templates 文件夹中
应用1的首页
-
制作app02的首页:
app02 下的urls:
from django.conf.urls import url
from app02 import viewsurlpatterns = [ url(r'^$',views.secondbase ), url(r'^home/',views.home ), ]
app02 下的views:
from django.shortcuts import render,HttpResponsedef home(request): return HttpResponse('应用界面02') def secondbase(request): return render(request,'app02base.html')
app02base.html 放在 模板 templates 文件夹中
应用2的首页
- 效果:
输入127.0.0.1:8000,就是项目的首页;
127.0.0.1:8000/app01/ ,就是应用1的首页;
127.0.0.1:8000/app02/ ,就是应用2的首页;
127.0.0.1:8000/app01/index 或者127.0.0.1:8000/app02/home还照样能拿到对应的内容
- 效果:
三、简单
-
url配置
urls.py文件中写在urlpatterns = []中
简单的路由
from app01 import views
url(r'^index/',views.index),
无名分组
url(r'^index/(\d+)/(\d+)/',views.index), --- def index(request,n,m) 位置参数
有名分组
url(r'^index/(?P\d+)/(?P \d+)/',views.index), -- def index(request,year,month) 关键字参数,参数顺序不要求 url(r'^index/$',views.index),
url(r'^index/(?P\d+)/,views.index),
视图函数参数默认值,
def index(request,num='1'):
print(num) -
路由分发
from django.conf.urls import url,include
url(r'app01/',include('app01.urls')),