目录
URLconf 配置
正则表达式详解
分组命名匹配
命名 URL 与 URL 反向解析
@
***
补充
获取项目内的所有 URL
from django.urls.resolvers import RegexURLPattern
from 项目名称 import urls # 与 setting.py 文件同级的 urls 文件
- def get_all_urls(urlpatterns, prev, is_first=False, result=[]):
- """获取项目所有的 URL"""
- if is_first:
- result.clear()
- for item in urlpatterns:
- v = item._regex.strip('^$')
- if isinstance(item, RegexURLPattern):
- result.append(prev + v)
- else:
- self.get_all_urls(item.url_patterns, prev + v)
- return result
- # 调用
- url_list = self.get_all_urls(urls.urlpatterns, prev='/')
Django 1.1 版本 URLConf 官方文档
URL 配置 (URLconf) 就像 Django 所支撑网站的目录, 它的本质是 URL 与要为调用的视图函数之间的映射表.
我们就是以这种方式告诉 Django, 遇到哪个 URL 的时候, 要对应执行哪个函数.
***
URLconf 配置
基本格式:
- from django.conf.urls import url
- urlpatterns = [
- url(正则表达式, views 视图, 参数, 别名),
- ]
参数说明:
正则表达式: 一个正则表达式字符串
views 视图: 一个可调用对象, 通常为一个视图函数
参数: 可选的要传递给视图函数的默认参数(字典形式)
别名: 一个可选的 name 参数(反向解析)
注意:
Django 2.0 版本中的路由系统是下面的写法(官方文档):
- from django.urls import path, re_path
- 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),
- ]
2.0 版本中的 re_path 和 1.11 版本的 url 是一样的用法.
***
正则表达式详解
基本配置:
- from django.conf.urls import url
- from . import views
- urlpatterns = [
- url(r'^test/[0-9]{4}/[0-9]{2}/$', views.test),
- url(r'^test/([0-9]{4})/$', views.test),
- url(r'^test/([0-9]{4})/([0-9]{2})/$', views.test),
- url(r'^test/([0-9]{4})/([0-9]{2})/([0-9]{2})/$', views.test),
- ]
注意事项:
==urlpatterns 列表中的元素按照书写顺序从上往下逐一匹配正则表达式, 一旦匹配成功则不再继续.==
若要从 URL 中获取一个值, 只需要在它周围放置一对圆括号(分组匹配).
不需要在匹配规则前面加斜杠(/), 因为每个 URL 都有, 例如应该这样写:"^articles", 而不是 "^/articles".
每个正则表达式前面的 "r", 是可选的, 但建议加上.
补充说明:
== 是否开启 URL 访问地址后面不为 "/" 时跳转至带有 "/" 的路径的配置项:==
APPEND_SLASH = True
Django 的 settings.py 文件中默认没有 APPEND_SLASH 这个参数, 但 == 此参数默认为开启状态 ==, 其作用是自动在网址结尾加 "/".
***
分组命名匹配
像上面的示例, 使用的是正则表达式分组匹配 (通过圆括号) 来捕获 URL 中的值并以位置参数形式传递给视图.
在更高级的用法中, 可以使用分组命名匹配的正则表达式组来捕获 URL 中的值, 并 == 以关键字参数形式传递给视图 ==.
在 Python 的正则表达式中, 分组命名正则表达式组的语法是 ==(?P<name>pattern)==, 其中 ==name== 是组的名称,==pattern== 是要匹配的模式.
下面是以上(基本配置)URLconf 使用命名组的重写:
- from django.conf.urls import url
- from . import views
- urlpatterns = [
- url(r'^test/(?P<year>[0-9]{4})/$', views.test),
- url(r'^test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.test),
- url(r'^test/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.test),
- ]
这种实现方式与前面的示例完全相同, 只有一个细微的差别:== 捕获的值作为关键字参数而不是位置参数传递给视图函数 ==.
例如, 针对 URL /articles/2019/10/ 相当于按以下方式调用视图函数:
views.test(request, year='2019', month='10')
在实际应用中, 使用分组命名匹配的方式可以让你的 URLconf 更加明晰且不容易产生参数顺序问题的错误, 但是有些开发人员则认为分组命名语法太丑陋, 繁琐.
至于究竟应该使用哪一种, 你可以根据自己的喜好来决定.
URLconf 匹配的位置:
URLconf 在请求的 URL 上查找, 将它当作一个普通的 Python 字符串,== 不包括 GET 和 POST 参数以及域名 ==.
例如:
URL 地址为 https:/ /blog.csdn.NET/test/ 的请求中, URLconf 将查找 / test/
URL 地址为 https:/ /blog.csdn.NET/test/?name=zyk 的请求中, URLconf 仍将查找 / test/
URLconf 不检查请求的方法. 换句话讲, 所有的请求方法 -- 同一个 URL 的 POST,GET,HEAD 等等, 都将路由到相同的函数.
捕获的参数永远都是字符串:
每个在 URLconf 中捕获的参数都作为一个普通的 Python 字符串传递给视图, 无论正则表达式使用的是什么匹配的方式. 例如, 下面这行 URLconf 中:
url(r'^test/(?P<year>[0-9]{4})/$', views.test),
传递给视图函数 views.test() 中的 year 参数永远是一个字符串类型.
视图函数中指定默认值
- from django.conf.urls import url
- from . import views
- urlpatterns = [
- url(r'^test/$', views.test),
- url(r'^test/(?P<num>[0-9]+)/$', views.test),
- ]
在上面的例子中, 两个 URL 模式指向相同的 view(view.test), 但是第一个模式并没有从 URL 中捕获任何东西.
如果第一个模式匹配上了, test()函数将使用其默认参数 num='1'; 如果第二个模式匹配上了, test()将使用正则表达式捕获到的 num 值.
include 其它的 URLconfs
指定到别的 URLconf 文件进行, 例如在默认的 urls.py 文件写如下匹配规则:
- from django.conf.urls import url, include
- from blog01 import views
- urlpatterns = [
- url(r'blog01/', include('blog01.urls')),
- ]
将所有路径为 blog01 开头的 URL 指向 blog01 下 urls.py 文件中去匹配.
传递额外参数给视图函数
URLconfs 具有一个钩子, 可以让我们传递一个 Python 字典作为额外的参数传递给视图函数.
django.conf.urls.url() 可以接收一个可选的第三个参数, 它是一个字典, 表示想要传递给视图函数的额外关键字参数, 如下:
- from django.conf.urls import url
- from . import views
- urlpatterns = [
- url(r'^test/$', views.test),
- url(r'^test/(?P<year>[0-9]{4})/$', views.test, {'month': '10'}),
- ]
在这个例子中, 对于 URL 地址为 /test/2019/ 的请求, Django 将调用 views.year_archive(request, year='2019', {'month': '10'})
== 当传递额外参数的字典中的参数与 URL 中捕获值的命名关键字参数同名时, 函数调用将使用字典的参数, 而不是 URL 中捕获的参数.==
***
命名 URL 与 URL 反向解析
在使用 Django 项目时, 一个常见的需求是获得 URL 的最终形式, 以用于嵌入到生成的内容中 (视图中和显示给用户的 URL 等) 或者用于处理服务器端的导航(重定向等).
.
人们强烈希望不要硬编码这些 URL(费力, 不可扩展且容易产生错误)或者设计一种与 URLconf 毫不相关的专门的 URL 生成机制, 因为这样容易导致一定程度上产生过期的 URL.
换句话讲, 需要的是一个 DRY 机制. 除了其它优点, 它还允许设计的 URL 可以自动更新而不用遍历项目的源代码来搜索并替换过期的 URL.
.
获取一个 URL 最开始想到的信息是处理它视图的标识 (例如名字), 查找正确的 URL 的其它必要的信息有视图参数的类型(位置参数, 关键字参数) 和值.
.
.Django 提供一个办法是让 URL 映射是 URL 设计唯一的地方. 你填充你的 URLconf, 然后可以双向使用它:
.
根据用户 / 浏览器发起的 URL 请求, 它调用正确的 Django 视图, 并从 URL 中提取它的参数需要的值.
根据 Django 视图的标识和将要传递给它的参数的值, 获取与之关联的 URL.
.
第一种方式是我们在前面的章节中一直讨论的用法. 第二种方式叫做反向解析 URL, 反向 URL 匹配, 反向 URL 查询或者简单的 URL 反查.
.
在需要 URL 的地方, 对于不同层级, Django 提供不同的工具用于 URL 反查:
.
. - 在模版中: 使用 url 模版标签.
在 Python 代码中: 使用 django.core.urlresolvers.reverse()函数.
在更高层的与处理 Django 模型实例相关的代码中: 使用 ge t_absolute_url()方法.
上面说了一大堆, 你可能并没有看懂.(那是官方文档的生硬翻译).
简单来说:
== 就是可以给我们的 URL 匹配规则起个名字(一个 URL 匹配模式起一个名字).==
== 这样我们以后就不需要写死 URL 代码了, 只需要通过 调用起的名字 来调用当前的 URL.==
例如:
- url(r'^home', views.home, name='home'), # 给我的 url 匹配模式起名为 home
- url(r'^index/(\d*)', views.index, name='index'), # 给我的 url 匹配模式起名为 index
在模版中这样引用:
- {
- % url 'home' %
- }
- {
- % url 'index' 2019 %
- }
- {
- % url 'index' key=2019 %
- }
在视图中这样引用:
- from django.urls import reverse
- reverse('index', args=('2019',))
- reverse('index', kwargs={
- key: '2019'
- })
图文示例(在模版中引用):
拿上面的例子来说, 如果出于某种原因决定按年归档文章发布的 URL 应该调整一下, 那么你将只需要修改 URLconf 中的内容.
在某些场景中, 一个视图是通用的, 所以在 URL 和视图之间存在多对一的关系. 对于这些情况, 当反查 URL 时, 只有视图的名字还不够.
注意:
为了完成上面例子中的 URL 反查, 你将需要使用命名的 URL 模式. URL 的名称使用的字符串可以包含任何你喜欢的字符, 不限制在合法的 Python 名称.
当命名 URL 模式时, 确保使用的名称不会与其它应用中的名称冲突. 如果你的 URL 模式叫做 comment, 而另外一个应用中也有一个同样的名称, 那么当你在模版中使用这个名称时, 不能保证将插入哪个 URL.
因此,== 在 URL 名称中加上一个前缀, 比如应用的名称, 将减少冲突的可能 ==. 我们建议使用 myapp-comment, 而不是 comment.
命名空间模式
即使不同的 App 使用相同的 URL 名称, URL 的命名模式也可以让你唯一反转命名的 URL.
例如:
- # project 中的 urls.py
- from django.conf.urls import url, include
- urlpatterns = [
- url(r'^app01/', include('app01.urls', namespace='app01')),
- url(r'^app02/', include('app02.urls', namespace='app02')),
- ]
- # app01 中的 urls.py
- from django.conf.urls import url
- from app01 import views
- app_name = 'app01'
- urlpatterns = [
- url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
- ]
- # app02 中的 urls.py
- from django.conf.urls import url
- from app02 import views
- app_name = 'app02'
- urlpatterns = [
- url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
- ]
现在, 我的两个 App 中 url 名称重复了, 我反转 URL 的时候就可以通过命名空间的名称得到我当前的 URL.
语法: =="命名空间名称: URL 名称"==
模版中使用:
{% url 'app01:detail' pk=12 pp=99 %}
views 中的函数中使用:
v = reverse('app01:detail', kwargs={'pk': 11})
这样即使 App 中 URL 的命名相同, 我们也可以反转得到正确的 URL.
来源: http://www.bubuko.com/infodetail-3149072.html