from django.url 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),
]
笔记
1.用尖括号从URL捕获值
2.捕获的值可以选择包括转换器类型。用<int:name>捕获整数参数,如果未包含转换器/,则匹配出字符之外的任何字符串
3.没有必要添加前导斜杠,因为每个URL都有。eg. articles ->not:/articles
eg.
1.请求/articles/2005/03/与列表中的第三个条目匹配。Django会调用该函数 。views.month_archive(request, year=2005, month=3)
2./articles/2003/将匹配列表中的第一个模式,而不是第二个模式,因为模式是按顺序测试的,第一个是第一个要通过的测试。随意利用订单插入这样的特殊情况。在这里,Django会调用该函数 views.special_case_2003(request)
3./articles/2003 不匹配任何这些模式,因为每个模式都要求URL以斜杠结尾。
4./articles/2003/03/building-a-django-site/将匹配最终模式。Django会调用该函数 。views.article_detail(request, year=2003, month=3, slug=“building-a-django-site”)
slug:用于生成一个有意义(valid, meaninful)URL 参考what is a slug in django->(http://stackoverflow.com/questions/427102/what-is-a-slug-in-django)
路径转换器
默认情况下,以下路径转换器可用:
str- 匹配除路径分隔符之外的任何非空字符串’/’。如果转换器未包含在表达式中,则这是默认值。
int - 匹配零或任何正整数。返回一个int。
slug - 匹配由ASCII字母或数字组成的任何slug字符串,以及连字符和下划线字符。例如, building-your-1st-django-site。
uuid - 匹配格式化的UUID。要防止多个URL映射到同一页面,必须包含短划线,并且字母必须为小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
path- 匹配任何非空字符串,包括路径分隔符 ‘/’。这允许您匹配完整的URL路径,而不仅仅是URL路径的一部分str。
注册自定义路径转换器
对于更复杂的匹配要求,您可以定义自己的路径转换器。
转换器是一个包含以下内容的类:
1.一个regexclass属性,作为字符串。
2.甲方法,它处理匹配的字符串转换成要传递到视图函数的类型。如果它不能转换给定值,它应该提高。to_python(self, value)ValueError
3.一种方法,用于处理将Python类型转换为要在URL中使用的字符串。to_url(self, value)
例如:
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/<yyyy:year>/', views.year_archive),
...
]
使用正则表达式
如果路径和转换器语法不足以定义URL模式,则还可以使用正则表达式。为此,请使用 re_path()而不是path()。
在Python正则表达式中,命名正则表达式组的语法是(?Ppattern),组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<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),
]
这完成了与前一个示例大致相同的事情,除了:
匹配的确切网址稍微受限制。例如,年份10000将不再匹配,因为年份整数被限制为恰好四位数。
无论正则表达式的匹配类型如何,每个捕获的参数都将作为字符串发送到视图。
从使用切换path()到 re_path()反之亦然,特别重要的是要注意视图参数的类型可能会发生变化,因此您可能需要调整视图。
指定视图参数的默认值
一个方便的技巧是为视图的参数指定默认参数。这是一个示例URLconf和视图:
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', 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捕获的任何值。
错误处理
当Django找不到所请求URL的匹配项时,或者引发异常时,Django会调用错误处理视图。
用于这些情况的视图由四个变量指定。它们的默认值应该足以满足大多数项目的需要,但可以通过覆盖它们的默认值来进一步自定义。
有关完整详细信息,请参阅有关自定义错误视图的文档。
可以在根URLconf中设置此类值。在任何其他URLconf中设置这些变量将不起作用。
值必须是callables或字符串,表示应该调用以处理手头错误条件的视图的完整Python导入路径。
变量是:
handler400
一个callable或一个字符串,表示视图的完整Python导入路径,如果HTTP客户端发送了导致错误情况的请求和状态代码为400的响应,则应该调用该路径。
默认情况下,这是django.views.defaults.bad_request()。如果您实现自定义视图,请确保它接受request和exception 参数并返回一个HttpResponseBadRequest。
handler403
一个callable或一个字符串,表示视图的完整Python导入路径,如果用户没有访问资源所需的权限,则应该调用该路径。
默认情况下,这是django.views.defaults.permission_denied()。如果您实现自定义视图,请确保它接受request和exception 参数并返回一个HttpResponseForbidden。
handler404
一个callable或一个字符串,表示视图的完整Python导入路径,如果没有任何URL模式匹配,则应该调用该路径。
默认情况下,这是django.views.defaults.page_not_found()。如果您实现自定义视图,请确保它接受request和exception 参数并返回一个HttpResponseNotFound。
handler500
一个callable或一个字符串,表示视图的完整Python导入路径,如果出现服务器错误,应该调用该路径。当视图代码中存在运行时错误时,会发生服务器错误。
默认情况下,这是django.views.defaults.server_error()。如果您实现自定义视图,请确保它返回一个 HttpResponseServerError。
包括其他的URLconf
在任何时候,您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/<int:id>/', 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('<page_slug>-<page_id>/history/', views.history),
path('<page_slug>-<page_id>/edit/', views.edit),
path('<page_slug>-<page_id>/discuss/', views.discuss),
path('<page_slug>-<page_id>/permissions/', views.permissions),
]
我们可以通过仅指定公共路径前缀一次并对不同的后缀进行分组来改进这一点:
from django.urls import include, path
from . import views
urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]