说明
DJango 只是一个网页框架
web 响应建议由 uwsgi + nginx 提供
高效的 URL 方案是高质量Web应用程序中的一个重要细节。
Django 允许你设计自定义的 URL,没有框架限制。使用 DJango时, 你需要创建一个Python模块, 这个模块是纯Python代码。
要利用 web 访问这个 Python 模块,通常需要 URLconf(URL配置)进行定义。路由是URL路径表达式到Python函数(视图)之间的映射。
这个映射可以是临时或者持久的。它可以引用其他映射。因为它是纯Python代码,所以可以动态构建。
Django还提供了一种根据活动语言来翻译URL的方法。
路由的作用
当用户从 Django 支持的站点请求页面时,系统将遵循以下算法来确定要执行哪些 Python 代码:
1 Django 通常默认下使用根 URLCONF 模块。使用 ROOT_URLCONF 设置的值
如果传入的 HttpRequest 对象中包含了 urlconf 属性(由中间件设置),则将使用它的值来代替默认的 ROOT_URLCONF 设置。
2 Django 加载 Python 模块并查找变量 URLPATH。
这应该是一个Python列表的Django.URL.PATH()和 / 或 Django.URL.RyPATH() 实例。
3 Django 按顺序运行每个 URL 模式,并在与请求的 URL 匹配的第一个站点上停止。
4 一旦一个 URL 模式匹配,Django 导入并调用指定的视图,这是一个简单的Python函数(或基于类的视图)。视图通过包含以下参数:
一个HTTPREQUEST的实例。
如果匹配的 URL 模式不返回命名组,则将正则表达式的匹配作为位置参数提供。
关键字 django.urls.path() 或 django.urls.re_path() 参数将会覆盖默认 ROOT_URLCONF 配置。
5 如果没有 URL 模式匹配,那么将会返回一个错误,并且 Django 将会调用的错误处理视图。
默认路由
默认在项目中 settting.py 配置文件中进行设定
ROOT_URLCONF = '项目命名.urls'
urls.py 格式定义
参考 urls.py 文件定义格式
urlpatterns = [
url(正则表达式, view函数, 参数, 别名),
]
example
静态定义方法
取官网 example
cat 项目/urls.py
from apps命名 import views
from django.conf.urls import url
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),
]
import 说明
from 项目命名 import views
导入 项目/views.py 文件
from django.conf.urls import url
导入默认路由配置
路由说明
ex1:
path('articles/2003/', views.special_case_2003),
定义了 http://x.x.x.x/articles/2003/ 访问路径
当有 http 请求上述访问路径,则访问 项目/views.py 文件中 special_case_2003 函数
ex2:
path('articles/<int:year>/', views.year_archive),
<int:year> 一种正则表达式
例如:定义了 http://x.x.x.x/articles/2018/ (匹配各个年份)
当有 http 请求上述或其他年份的 URL 都会调用 项目/views.py 文件中 year_archive 函数
函数会自动读入变量 year_archive(request, year=2018):
ex3:
path('articles/<int:year>/<int:month>/', views.month_archive),
<int:year>/<int:month>/ 路径定义方法
例如:定义了 http://x.x.x.x/articles/2018/04/
当有 http 请求上述或其他年份的 URL 都会调用 项目/views.py 文件中 month_archive 函数
函数会自动读入变量 month_archive(request, year=2018, month=04):
ex4:
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
<int:year>/<int:month>/ 一种正则表达式(匹配了年与月格式)
<slug:slug> 一种正则表达方法, 定义了任意合法的 URL 规则
例如: 定义了 http://x.x.x.x/articles/2018/04/it-my-example/
当有 http 请求上述或其他年份的 URL 都会调用 项目/views.py 文件中 article_detail 函数
函数会自动读入变量 article_detail((request, year=2018, month=04,slug='it-my-example'):
疑问
假如我访问下面 url, 会发生什么情况?
ex:
http://x.x.x.x/articles 或 http://x.x.x.x/articles/
该访问无法匹配上述指定的任意 URL 路由
ex2:
http://x.x.x.x/articles/2003
该访问无法匹配上述指定的任意 URL 路由
因为正确语法, 必须在 结尾加入 '/' 符号
ex3
http://x.x.x.x/articles/2003/
匹配了第一条规则
因为在匹配路由规则时候,会从上至下进行匹配,一旦满足, 则不再对其他规则生效
ex4:
http://x.x.x.x/articles/99999/
这个是一个合法的访问, 匹配了 path('articles/<int:year>/', views.year_archive), 语法
year 只是一个变量定义命名,99999 只是作为一个 int 类型的值而已
路径转换
参考一下可用的路径类型定义方法
str - 匹配任何非空字符串,不包括路径分隔符,'/'。如果表达式中未包含转换器,则为默认值。
int - 匹配零或任意正整数。返回int。
slug - 匹配任何 ASCII 字母或数字,底线和下划线字符串组成的字符串。
uuid - 匹配格式化的UUID。为了防止多个URL映射到同一个页面,必须包含破折号,并且字母必须是小写的。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回UUID实例。
path - 匹配任何非空字符串,包括路径分隔符,'/'。
对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:
regex 类属性,字符串类型
to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
ex:
一个转换成为 4 位年份的转发器
把代码保存至下面文件中 apps/converters.py
class FourDigitYearConverter:
regex = '[0-9]{4}'
def to_python(self, value):
return int(value)
def to_url(self, value):
return '%04d' % value
重新定义 项目/urls.py
from django.urls import path, register_converter
from apps命名 import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<yyyy:year>/', views.year_archive),
...
]
说明:
path('articles/<yyyy:year>/', views.year_archive),
这里 yyyy 就是使用了自定义的转换器
转换器 register_converter(converters.FourDigitYearConverter, 'yyyy') 在这里进行了定义
代码将会从 from apps命名 import converters 这里进行读取
使用正则
参考下面使用正则使用之前功能
需要使用 re_path() 代替 path()
from django.urls import path, re_path
from apps命名 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),
]
使用二级路由
参考下面例子
from django.urls import path
from apps命名 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 apps命名 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),
])),
]