在当代的web应用中,清晰优雅的URL非常重要,在Django框架中,你可以随心所欲的设计你的URL,不用担心框架的限制。
概览
为了给一个app设计URL,你创建一个Python模块叫做URLConf
,这个模块是纯Python代码并且用于于映射URL路径和Python的功能或视图。
这个映射关系可以写的比较短,它也可以引用其它的映射,并且由于它是纯代码,所有它可以动态的构建。
Django如何处理请求
当用户请求一个由Django构建的网站,下面是Django的处理方式来决定执行那一部分的Python代码
- Django找到root(根)URLconf模块,根模块一般与项目同名的目录下,当然这个可以在ROOT_URLCONF配置中设置,但是如果请求的HttpRequest对象由urlconf属性(通过中间件设置),它的值将会用于替换 ROOT_URLCONF的设置。
- Django加载python的模块,然后朝找urlpattern变量,这个应该是一系列的
django.urls.path()
或者django.urls.re_path()
的实例 - Django遍历URL样式,在第一个匹配请求的时候停止遍历。
- 一旦其中的一个URL样式被匹配了,django导入和调用提供的视图,一般是Python的函数,视图将会传递下面的参数
- 一个HttpRequest的实例
- 如果匹配的URL样式返回无命名的组,那么从正则表达式中匹配的部分将作为对应位置的参数
- 关键参数由匹配路径表达式的命名部分组成,由指定的参数覆盖.
- 如果没有URL匹配,或者抛出了异常,Django将会调用一个合适的错误处理视图。
案例
from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
注意:
- 想要从URL中捕捉值,使用尖括号
- 捕捉值可以包含转换后的类型,例如int:name捕捉的是整数,如果转换器没有包括进来,任何字符串除了
/
也可以匹配 - 在开头部分不需要天剑
/
,因为它是articles
,不是/articles
请求映射:
- 请求/article/2005/03/ 对应列表中的第三个条目,django会调用views.month_archive(request,year=2005,month=3)
- 请求 /article/2003/ 对应列表中的第一个,因为django找到符号规则的就停下来了。调用views.special_case_2003(request)函数
- /article/2003 不会匹配任何一个条目,因为每一个条目后面都有一个
/
- /articles/2003/03/building-a-django-site/ 匹配最后一个条目,调用views.article_detail(request, year=2003, month=3, slug=“building-a-django-site”) 函数
Path Converter(路径转换器)
下面这些是默认可用的转换器
- str: 匹配非空字符串,除了
/
。这个是默认的转换器 - int 匹配0或者任何正整数
- slug 匹配ASCII租车的字符串,加上
-
和_
。例如today_is-2018-10
也可以 - path 匹配非空的字符串,包含
/
,这个可以匹配一个完整的URL,而不仅仅是路径中的一个片段(str)
当然也可以注册自己的转换器,也不麻烦,可以参考官方文档
使用正则表达式
如果路径转换器的语法不够高效来定义你的URL样式,你可以使用正则表达式,这时使用re_path
,而不是path
正则表达式的语法为:
(?Ppattern) ,name是组名,pattern是要匹配的样式
看下面的例子,这样的表达实现了和刚才使用转换器同样的功能。
from django.urls import path, re_path
from . import views
urlpatterns = [
path('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<slug>[\w-]+)/$',views.article_detail),
]
额外
- URLconf模块只是用来匹配路径,并不处理请求方法,像GET,POST,PUT等不同类型的请求也会路由到同一个Python函数中。
- 使用include可以引入其他的url模块。
最后
以上的基本能满足初步的开发,先暂时到这里。