url配置就像Django所支撑网站的目录。它的本质是url与要被该url调用的视图函数之间的映射表;通过这个映射表可以告知Django,对于客户端发来的某个url该执行那些代码。
一、简单的路由配置
from django.urls import path,re_path
from app01 import views
urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
path('articles/2003/',views.special_case_2003), 这一句和上一句的效果一样,path自动加上了开头^和结尾&
re_path(r'^articles/([0-9]{4})/$', views.year_archive),
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 带()就是分组,只要分组的数据就可以作为位置参数传给视图函数
re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
re.path()相当于要自己写正则来匹配url,如果发过来的url的能匹配上,那就执行相对应的views;
不需要添加一个前导的反斜杠,因为你不用写,它会自动给你加上一个/,如果你写了一个前导的反斜杠,匹配的时候就会成了两个反斜杠,这样会报错的
'''
一些请求的例子:
/articles/2005/03/ 请求将匹配列表中的第三个模式。Django 将调用函数views.month_archive(request, '2005', '03')。
/articles/2005/3/ 不匹配任何URL 模式,因为列表中的第三个模式要求月份应该是两个数字。
/articles/2003/ 将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。
/articles/2003 不匹配任何一个模式,因为每个模式要求URL 以一个反斜线结尾。
/articles/2003/03/03/ 将匹配最后一个模式。Django 将调用函数views.article_detail(request, '2003', '03', '03')。
'''
二、有名分组
上面我们说了,带()就是进行了分组,就会作为位置参数传给视图函数,视图函数也要以位置来区分每个数据,当数据很庞大时,就会混乱;其实我们在正则里面可以给分组的取个名字,如果分组的有名字了就会以关键字参数的形式传给视图函数,此时视图函数就要以每组的名字来接收数据,顺序都是无所谓的。
from django.urls import path,re_path
from app01 import views
urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
'''请求的例子
/articles/2005/03/ 请求将调用views.month_archive(request, year='2005', month='03')函数,而不是views.month_archive(request, '2005', '03')。
/articles/2003/03/03/ 请求将调用函数views.article_detail(request, year='2003', month='03', day='03')。
'''
三、分发
我们知道哈,在每个应用中有views,models,相当于说每个应用有自己的视图文件和模板文件,但没有自己单独的url,在整个项目里面有一个共同的urls,也就就是说大家共用一个urls,其实这样解耦不好,其实我们可以自己为每一个应用加上一个url,再做一个分发就行了。
'''
At any point, your urlpatterns can “include” other URLconf modules. This
essentially “roots” a set of URLs below other ones.
'''
from django.urls import path,re_path,include
from app01 import views
urlpatterns = [
re_path(r'^admin/', admin.site.urls),
re_path(r'^blog/&', include('blog.urls')), blog就是一个应用,当请求路径为/blog/时,先到全局的urls中找,找到blog.urls,相当于找到了blog应用下的urls,从此,我们就可以把每个应用的路由配置写在自己的urls中
]
四、反向解析
反向解析是挺难理解的。在HTML文件中的a标签需要写一个路径,还有form表单中也是,其实我们不需要直接把路径写上去,可以用一个代号,这样写的好处在于:如果要求我们把HTML中的路径改了,那我们是不是一个一个的把所有的都该了,如果有无数多个,那我们就得该无数次,这样效率太低,但我们用反向解析就一下解决了。
在需要url的地方,对于不同层级,Django提供不同的工具用于url反查:
1,在模板中,使用url模板标签
2,在python代码中,使用from django.urls import reverse
urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
#...
re_path(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
#...
]
在HTML文件中
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
python逻辑中
from django.urls import reverse
from django.http import HttpResponse,redirect
def redirect_to_year(request):
# ...
year = 2006
# ...
return redirect(reverse('news-year-archive')) # 同redirect("/path/")