django学习手记(五)------path
原创从’ https://docs.djangoproject.com/en/3.0/topics/http/urls/ ‘ 翻译来
path
Django如何处理请求
当用户从Django当受支持的站点请求页面时,系统将按照以下算法确定要执行的操作。Python代码:
-
Django确定要使用的根URLconf单元通常,这是根 ROOT_URLCONF设置值,但如果传入HttpRequest对象具有 urlconf属性(由中间件设置),将使用其值而不是根ROOT_URLCONF设置。
-
Django加载Python模块并查找变量urlpatterns。这应该是django.url.path()和/或django.url.re_path()实例的顺序。
-
Django按顺序遍历每个URL模式,与请求的URL先匹配URL停止时,path_info匹配。
-
一次URL模式匹配,Django导入并调用给定的视图,该视图是Python函数(或基于类的视图)。该视图传递以下参数:
(1) HttpRequest一个实例。
(2)如果匹配URL如果模式不包含命名组,则正则表达式中的匹配将作为位置参数提供。
(3关键字参数由与提供的路径表达式匹配的任何命名部分组成,并且是可选的。kwargs参数中指定的任何参数都将被重写。django.urls.path()或django.urls.re_path()。
(4)在Django 3.0中更改:
在旧版本中,没有值的关键字参数也用于未提供的命名零件。 -
如果没有匹配URL模式或异常在过程中的任何时间发生,Django将调用适当的错误处理视图。请参阅下面的错误处理。
例 下面是URLconf示例:
from django.urls import path
from . import views
urlpatterns = [
path(articles/2003/, views.special_case_2003),
path(articles//, views.year_archive),
path(articles///, views.month_archive),
path(articles////, views.article_detail),
]
笔记:
- 要从URL捕获值,使用尖括号。
- 捕获的值可以选择性地包括转换器类型。例如,使用int:name捕获整数参数。如果不包括转换器,匹配将被分割。a/字符以外的任何字符串。
- 不需要添加前导斜杠,因为每个URL都有前导斜线。例如,它是一篇文章,而不是/文章。
请求示例:
- 对/articles/2005/03/请求将与列表中的第三个条目匹配。Django将调用该函数views.month_archive(请求,year=2005,month=3)。
- /articles/2003/将匹配列表中的第一个模式而不是第二个模式,因为这些模式是按顺序测试的,第一个模式是第一个通过的测试。请随时使用命令插入这样的特殊情况。在这里Django将调用该函数视图views.special_case_2003(request)
- /articles/2003与这些模式都不匹配,因为每个模式都需要URL以斜线结尾。
- /articles/2003/03/building-a-django-site/将匹配最终图案。Django将调用该函数views.article_detail(request,year=2003,month=3,slug=“building-a-Django-site”)。
路径转换器
默认情况下,以下路径转换器可用:
- str-匹配任何非空字符串,路径分隔符“/“。如果表达式不包含转换器,则这是默认值。
- int-匹配零或任何正整数。返回int。
- slug-匹配由ASCII字母或数字加上连字符和下划线。slug一串例如building-your-1st-django-site。
- uuid-匹配格式uuid。为了防止URL映射到同一页必须包含破折号,字母必须为小写。例如075194d3-6885-417e-a8a8-6c931e272f00.。返回UUID实例。
- path-匹配任何非空字符串,包括路径分隔符“/“。这允许您匹配URL路径,而不是类似str那样匹配URL路径的一段。
注册自定义路径转换器
对于更复杂的匹配要求,您可以定义自己的路径转换器。
转换器是包含以下内容的类:
- regex类属性,作为字符串。
- to_python(self,value方法,用于将匹配字符串转换为。view函数类型。如果给定值无法转换ValueError。ValueError被解释为不匹配,因此除非另有说明URL模式匹配,否则将发送给用户。404响应。
-
to_url(self,value)方法,用于传输Python将转换为的类型转换为。url中使用的字符串。
例如:class FourDigitYearConverter: regex = [0-9]{4} def to_python(self, value): return int(value) def to_url(self, value): return %04d % value
使用Register_converter()在URLconf在以下位置注册自定义转换器类:
from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, yyyy)
urlpatterns = [
path(articles/2003/, views.special_case_2003),
path(articles//, views.year_archive),
...
]
使用正则表达式
如果路径和转换器语法不足以定义URL模式,您也可以使用正则表达式。为此,请使用re_path改为()path()。
在Python在正则表达式中,命名正则表达式组的语法为
(?P< name>pattern),其中name是组的名称,pattern是要匹配的模式。
这是前面的例子URLconf,使用正则表达式重写:
from django.urls import path, re_path
from . import views
urlpatterns = [
path(articles/2003/, views.special_case_2003),
re_path(r^articles/(?P[0-9]{4})/$, views.year_archive),
re_path(r^articles/(?P[0-9]{4})/(?P[0-9]{2})/$, views.month_archive),
re_path(r^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[w-]+)/$, views.article_detail),
]
这实现了与前一个示例大致相同的功能:
- 要匹配的确切匹配url有点有限。例如,年份10000将不再匹配,因为年份整数的长度限制为四位数。
- 无论正则表达式的匹配类型如何,每个捕获的参数都作为字符串发送到视图。
当从使用path()切换到重用re_path() 反之亦然,特别重要的是要注意,视图参数的类型可能会更改,因此可能需要调整视图。
使用未命名的正则表达式组
以及命名组语法,例如。(?P< year>[0-9]{4}),也可以使用较短的未命名组,例如([0-9]{4})。
不特别推荐这种用法,因为它更容易意外地在匹配的预期含义和视图参数之间引入错误。
在这两种情况下,建议在给定的正则表达式中仅使用一种样式。当这两种样式混合时,将忽略任何未命名的组,仅将命名的组传递给view函数。
嵌套参数
正则表达式允许嵌套参数,Django它们被解决并传递给视图。当倒车时,Django将尝试填充所有外部捕获的参数,忽略任何嵌套的捕获参数。考虑以下内容URL模式,可以选择使用页面参数:
from django.urls import re_path
urlpatterns = [
re_path(r^blog/(page-(d+)/)?$, blog_articles), # bad
re_path(r^comments/(?:page-(?Pd+)/)?$, comments), # good
]
这两种模式都使用嵌套参数和解析:例如,blog/page-2/将导致与blog_articles匹配的,包含两个位置参数:page-2/和2。comments第二种模式将匹配。comments/page-2/以及关键字参数page_number设置为2在此示例中,外部参数是非捕获参数。(?:…).
blog_articles在这种情况下,视图需要反转最外部捕获的参数。page-2/或者没有参数,而注释可以用没有参数或页码的值反转。
嵌套捕捉参数在视图参数和中。URL在,blog_articles显示:查看接收URL零件(page-2/),而不是只接收视图感兴趣的值。这种耦合在反转中更为明显,因为要反转视图,我们需要传递URL片段而不是页码。
根据经验,当正则表达式需要参数但视图忽略它时,只捕获视图需要使用的值,并使用未捕获的参数。
URLconf搜索的内容
URLconf作为一个普通人Python请求字符串对。URL搜索这不包括GET或POST参数或域名。
例如,在https://www.example.com/myapp/在该请求中,URLconf将查找myapp/。
在对https://www.example.com/myapp/在请求中?page=3,URLconf将查找myapp/。
URLconf不要查看请求方法。换句话说,所有请求方法(POST、GET、HEAD依此类推)将被路由到相同的URL具有相同的功能。
指定视图参数的默认值
一种方便的方法是为视图的参数指定默认参数。下面是URLconf和view的示例:
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path(blog/, views.page),
path(blog/page/, views.page),
]
# View (in blog/views.py)
def page(request, num=1):
# Output the appropriate page of blog entries, according to num.
...
在上面的示例中,两个URL模式都指向同一视图views.page,但第一个模式不是从URL捕获任何内容。如果第一模式匹配,page()该函数将使用num,1默认参数的。如果第二模式匹配,page()将使用任何捕获的num值。
表现
urlpatterns中的每个正则表达式都是在第一次访问时编译的。这使得系统速度惊人。
urlpatterns变量的语法
urlpatterns应该是path()和/或re_path()实例的顺序。
错误处理
当Django找不到请求的URL或者当抛出异常时,Django调用错误处理视图。
这些案例的视图由四个变量指定。它们的默认值应该能够满足大多数项目的需要,但是可以通过覆盖它们的默认设置值来进一步定制它们。 有关更多信息,请参阅有关自定义错误视图的文档。
这些值可以位于根。URLconf产生在任何其他URLconf这些变量都没有任何影响。
该值必须是可调用的或表示完整视图。Python导入路径的字符串,应该调用该字符串来处理当前的错误条件。
变量包括:
handler400–请参阅django.conf.urls.handler400。
handler403–请参阅django.conf.urls.handler403。
handler404–请参阅django.conf.urls.handler404。
handler500–请参阅django.conf.urls.handler500。
包括其他URLconfs
在任何时候,urlpatterns可以“包括”其他URLconf单元这本质上是一个“根”组,位于另一个URL下面的URL。
例如,这里是Django网站本身URLconf摘录。它包括一些其他urlconf:
from django.urls import include, path
urlpatterns = [
# ... snip ...
path(community/, include(aggregator.urls)),
path(contact/, include(contact.urls)),
# ... snip ...
]
每当Django遇到include(),它将切断匹配点。URL并将剩余的字符串发送给包含的。URLconf用于进一步处理。
另一种可能性是使用path()包含其他实例的实例列表URL模式例如,考虑一下URLconf:
from django.urls import include, path
from apps.main import views as main_views
from credit import views as credit_views
extra_patterns = [
path(reports/, credit_views.report),
path(reports//, credit_views.report),
path(charge/, credit_views.charge),
]
urlpatterns = [
path(, main_views.homepage),
path(help/, include(apps.help.urls)),
path(credit/, include(extra_patterns)),
]
在这个例子中,/credit/reports/URL将由credit-views.report()Django查看处理。
这可以通过重用单个模式前缀来使用。urlconf删除冗余。例如,考虑一下URLconf:
from django.urls import path
from . import views
urlpatterns = [
path(-/history/, views.history),
path(-/edit/, views.edit),
path(-/discuss/, views.discuss),
path(-/permissions/, views.permissions),
]
我们可以通过只声明一次公共路径前缀并将不同后缀分组来改进这一点:
from django.urls import include, path
from . import views
urlpatterns = [
path(-/, include([
path(history/, views.history),
path(edit/, views.edit),
path(discuss/, views.discuss),
path(permissions/, views.permissions),
])),
]
捕捉参数
包含的URLconf从父URLconf接收任何捕获的参数,因此以下示例有效:
# In settings/urls/main.py
from django.urls import include, path
urlpatterns = [
path(/blog/, include(foo.urls.blog)),
]
# In foo/urls/blog.py
from django.urls import path
from . import views
urlpatterns = [
path(, views.blog.index),
path(archive/, views.blog.archive),
]
在上面的示例中,捕获的“username“变量按预期传递给包含的URLconf。
传递其他选项以查看函数。
urlconf有一个钩子可以接受其他参数。Python字典被传递给视图函数。
path()函数可以接受应传递的可选第三个参数。view函数的附加关键字参数字典。
例如:
from django.urls import path
from . import views
urlpatterns = [
path(blog//, views.year_archive, {foo: bar}),
]
在这个例子中,对于对/blog/2005/的请求,Django将调用views.year_archive(request,year=2005,foo=‘bar’)。
联合框架中使用此技术将元数据和选项传递给视图。
处理冲突
它可能有一个URL模式,它捕获命名的关键字参数并在其附加参数字典中传递具有相同名称的参数。当这种情况发生时,将使用字典中的参数。URL中捕获的参数。
向include()传递其他选项
类似地,您可以将其他选项传递给include(),包含URLconf中的每一行都将传递其他选项。
例如,这两个URLconf集合功能相同:
设置一:
# main.py
from django.urls import include, path
urlpatterns = [
path(blog/, include(inner), {blog_id: 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path(archive/, views.archive),
path(about/, views.about),
]
设置二:
# main.py
from django.urls import include, path
from mysite import views
urlpatterns = [
path(blog/, include(inner)),
]
# inner.py
from django.urls import path
urlpatterns = [
path(archive/, views.archive, {blog_id: 3}),
path(about/, views.about, {blog_id: 3}),
]
请注意,附加选项将始终传递给包含的URLconf中的每一行,无论该行的视图是否实际接受这些选项为有效。因此,只有在您确定包含的情况下。URLconf只有当中的每个视图接受您传递的其他选项时,此技术才有用。
URL反向分辨率
在Django在进行项目时,一个常见的要求是可以获得最终表格。url,用于嵌入生成的内容(视图和资产)url,显示给用户。url等),用于处理服务器端导航流(重定向等)
人们强烈希望避免这些url硬编码(一种费力、不可扩展且容易出错的策略)。设计一些特殊机制来生成和URLconf所描述的设计是并行的。url,这可能导致url随着时间的推移,这一代人已经过时了。
换句话说,我们需要的是一个干燥的机制。除其他优点外,它将允许URL设计进化,无需遍历所有项目源代码来搜索和替换过时的URL。
我们获得URL主要信息负责处理URL视图的标识(例如名称)。必须参与权利URL找到的其他信息是视图参数的类型(位置、关键字)和值。
Django提供一种解决方案URL映射器是URL唯一设计的存储库。您可以使用URLconf输入它,然后它可以用于两个方向:
- 从用户/浏览器请求URL开始,它调用正确的Django视图,提供自URL提取值可能需要的任何参数。
- 从对应的Django视图的标识以将传递给它的参数值开始,并获取关联的。URL。
第一个是我们在前面几节中讨论的用法。第二种是所谓的URL反向解析,反向URL匹配,反向URL查找或简单URL反向。
Django提供执行URL与需求相关的逆转工具URL不同的匹配层:
- 在模板中:使用url模板标记。
- 在Python代码:使用。reverse()函数。
- 在与处理Django模型实例。url在相关高级代码中:get_absolute_url()方法。
例 再考虑一下URLconf条目:
from django.urls import path
from . import views
urlpatterns = [
#...
path(articles//, views.year_archive, name=news-year-archive),
#...
]
根据这种设计,nnnn存档对应的年份。URL是/articles//。 您可以使用以下方法在模板代码中获取此信息:
2012 Archive
{# Or with the year in a template context variable: #}
{% for yearvar in year_list %}
- {{ yearvar }} Archive
{% endfor %}
或者在Python代码中:
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse(news-year-archive, args=(year,)))
如果出于某种原因,决定改变已发表年度文章的档案内容。url,那么你只需要改变URLconf中的条目。
在一些视图具有通用性质的场景中,url和视图之间可能存在多对一关系。在这些情况下,当url视图名称不是足够好的标识符。阅读下一节以了解Django为此提供了解决方案。
命名URL模式
为了执行URL相反,您需要使用上面示例中的命名。URL模式对于URL名称字符串可以包含任何您喜欢的字符。对有效成分的使用没有限制Python名称。
在命名URL模式下,选择一个不太可能与其他应用程序的名称选择冲突的名称。如果呼叫URL当另一个应用程序执行相同操作时,reverse找到()URL取决于项目的urlpatterns列表中的最后一个模式。
在URL该名称带有前缀(可能源于应用程序名称)(例如。myapp comment而不是comment),可以减少冲突的可能性。
如果要覆盖视图,可以故意选择与其他应用程序相同的视图。URL名称例如,一个常见的用例是重写LoginView。Django大多数第三方应用程序都假定此视图具有名称。login的URL模式如果您有一个自定义登录视图并将其放入。URL命名为login,reverse()将包含在django.contrib.auth.urls之后(如果包括)urlpatterns在中查找自定义视图。
如果多个URL模式的参数不同,或者可以使用相同的名称。此外URL除了名字,reverse()还匹配参数的数量和关键字参数的名称。
URL命名空间
导言
URL命名空间允许您唯一地反转命名URL模式,即使不同的应用程序使用相同的模式URL名称对于第三方应用程序,请始终使用命名空间。url是一个很好的实践(正如我们在教程中所做的那样)。同样,如果部署了应用程序的多个实例,它也允许您进行反向操作。url换句话说,因为单个应用程序的多个实例将共享url,命名空间提供了区分这些命名的方法url的方法。
正确使用URL命名空间Django可以为特定站点多次部署应用程序。例如django.contrib.admin有一个AdminSite类,允许您部署多个admin例子在后面的示例中,我们将在本教程中讨论在两个不同位置部署。polls该应用的想法是,我们可以为两个不同的受众(作者和出版商)提供相同的功能。
URL命名空间分为两部分,这两部分都是字符串:
应用程序命名空间
这描述了正在部署的应用程序的名称。单个应用程序的每个实例将具有相同的应用程序名称空间。例如Django管理应用程序具有可预测的应用程序命名空间“admin”。
实例命名空间
它标识应用程序的特定实例。实例名称空间在整个项目中应该是唯一的。但是,实例名称空间可以与应用程序名称空间相同。这用于指定应用程序的默认实例。例如,默认Django管理实例的实例命名空间为“admin”。
使用“:”运算符指定命名空间。URL。例如,使用“admin:index“指管理应用程序的主索引页。这意味着”admin“命名空间和”index”的命名URL。
命名空间也可以嵌套。命名URL“sports:polls:index“将在命名空间中”polls“查找名称”index,命名空间本身在顶级命名空间中sports“如中所定义。
反向命名空间URL
当给定要解析的命名空间时URL(例如“polls:index”)时,Django将完全限定名拆分为多个部分,然后尝试以下查找:
- 首先,Django查找匹配的应用程序命名空间(在本例中为“polls“)。这将生成应用程序实例列表。
- 如果定义了当前应用,Django将查找并返回实例的URL分析器。可以使用reverse()函数current_app该参数指定当前应用程序。
url模板标记使用当前解析视图的命名空间作为RequestContext中的当前应用程序。你可以进去。request.current_app在属性上设置当前应用程序以覆盖此默认值。 - 如果没有当前应用,Django将查找默认应用程序实例。默认应用程序实例是具有与应用程序命名空间匹配的实例命名空间实例(在这个例子中,是一个名为“polls”的polls实例)。
- 如果没有默认应用实例,Django将选择应用程序的最后一个部署实例,而不考虑其实例名称。
- 如果在步骤中1中提供的命名空间与应用程序命名空间不匹配,Django将尝试直接将命名空间作为实例命名空间查找。
如果存在嵌套的命名空间,请对命名空间的每个部分重复这些步骤,直到只有视图名称未解析。然后将视图名称解析为找到的命名空间。URL。
例
要实际显示此解决策略,请考虑本教程。polls应用程序的两个实例:一个称为“author polls“,另一个称为”publisher polls“。假设我们增强了应用程序,以便在创建和显示轮询时考虑实例命名空间。
#url.py
from django.urls import include, path
urlpatterns = [
path(author-polls/, include(polls.urls, namespace=author-polls)),
path(publisher-polls/, include(polls.urls, namespace=publisher-polls)),
]
#polls/urls.py
from django.urls import path
from . import views
app_name = polls
urlpatterns = [
path(, views.IndexView.as_view(), name=index),
path(/, views.DetailView.as_view(), name=detail),
...
]
使用此设置,可以执行以下查找:
- 如果其中一个实例是当前实例(例如,如果我们正在渲染一个实例“author-polls“在详细信息页中),”polls:index“将决心”author-polls实例的索引页,即以下两个实例都将生成/author-polls/”。
在基于类的视图的方法中:
reverse(polls:index, current_app=self.request.resolver_match.namespace)
在模板中:
{% url polls:index %}
- 如果没有当前实例,例如,如果我们在网站的其他位置显示页面,“polls:index“会解决的。polls最后注册的实例。由于没有默认实例(“polls“实例命名空间),将使用注册的polls最后一个实例。这将是“publisher-polls“因为它在里面。urlpatterns声明是最后一份。
- “author-polls:index“将始终解析为实例”author- polls“索引页(用于”publisher-polls“也是)。
如果仍有一个默认实例,即名为“polls如果没有当前实例(上面列表中的第二项),与上面的实例相比,唯一的变化是。在这种情况下polls:index“会解决的。默认实例的索引页,而不是urlpatterns中最后一个声明的实例。
URL命名空间和包含URLconfs
包含的urlconf可以通过两种方式指定应用程序名称空间。
首先,可以包括在URLconf设置在模块中app_name属性,其级别与urlpatterns属性相同。必须按顺序传递模块的实际模块或字符串引用include(),而不是urlpatterns自身列表。
#polls/urls.py
from django.urls import path
from . import views
app_name = polls
urlpatterns = [
path(, views.IndexView.as_view(), name=index),
path(/, views.DetailView.as_view(), name=detail),
...
]
#urls.py
from django.urls import include, path
urlpatterns = [
path(polls/, include(polls.urls)),
]
polls.url中定义的urls将具有应用程序命名空间。polls。
其次,可以包含包含嵌入命名空间数据的对象。如果include(),path()或re_path()对象包含的实例列表。URL将添加到全局命名空间。但是,您也可以include()一个2元组,包含:
(, )
例如:
from django.urls import include, path
from . import views
polls_patterns = ([
path(, views.IndexView.as_view(), name=index),
path(/, views.DetailView.as_view(), name=detail),
], polls)
urlpatterns = [
path(polls/, include(polls_patterns)),
]
这将包括给定应用程序命名空间中指定的。URL模式。
可以使用命名空间参数include()指定实例命名空间。如果未指定实例名称空间,则默认为包含URLconf的应用程序命名空间。这意味着它也将是该命名空间默认实例。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123



