Django 之 路由层
1. Django的请求生命周期流程图
# 帮助我们梳理django框架的执行顺序
2. 路由层
1. 路由匹配,urls.py
"django1"
支持正则匹配
后面版本是精准匹配:path,re_path
APPEND_SLASH = True # 默认
"匹配规则:从上到下只要正则表达式匹配成功,就不会往下匹配了"
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'test', view.test),
url(r'testadd', view.test)
]
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^test/', views.test),
uru(r'^testadd/', views.test),
]
"get请求的传参方式:"
1. http://127.0.0.1:8000/test/?a=1
2. http://127.0.0.1:8000/test/1
url(r'^test/(\d+$)') 无名分组传参
2.1 无名分组和有名分组
url(r'^test/(\d+$)')
# 无名分组传参随便传,把括号中的数字当作参数传给视图函数。
url(r'^test/(?P<aaa>\d{2})$')
有名分组只能位置传参
匹配的数字通过位置传给视图函数
2.2 反向解析
# 反向解析就是通过一个路由别名可以得到别名所在的这行路由的完整地址。
url(r'^test/', views.test, name='test'),
# views
reverse('test')
# 带参数的反向解析
url(r'^test/(\d+)', views.test, name='test')
# views
reverse('test', args=(111))
reverse('test', kwargs=('aa','bb'))
"有名和无名不能混合使用,可以单个多次使用"
说白了就是路由不想写死,路径的硬编码
在使用django 项目时,一个常见的需求是获得 URL 的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的 导航(重定向等)。人们强烈希望不要硬编码这些 URL(费力,不可扩展 且 容易产生错误)或者设计一种与 URLconf 毫不相关的专门的 URL 生成机制,因为这样容易导致一定程度上产生过期的 URL。
在需要 URL的地方,对于不同层级,Django提供不同的工具用于URL反查:
- 在模板中:使用url模板标签
- 在Python 代码中:使用from django.urls import reverse 函数。
urls.py中为 url设置别名参数:
from django.conf.urls import url
from . import views
urlpatterns = [
# ...
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
# ...
]
应用之 在模板函数中反向解析:
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
<a href="/articles/2012/">2012 Archive</a>
应用之 在py文本中反向解析:
from django.shortcuts import redirect
from django.urls import reverse
def redirect_to_year(request):
year = 2008
reverse_path=reverse('new-year-archive', args=(year,))
return redirect(reverse_path) # 等效 redirect("/articles/2008/")
3. 路由分发(重点)
# 以后的django项目会越来越大,那么就会导致总路由文件会越来越大,就会非常难维护
# 我们就会把总路由分开到不同的应用下面。
"django的每一个应用都支持有自己的urls.py,templates,static"
# 怎么样把这些应用串起来,就是使用路由分发
# 使用路由分发是存在多个应用的时候
4. 名称空间
# 当多个应用出现相同的别名时,反向解析就没办法识别了。
include(app01.urls, namespace="xxx")
reverse('xxx:index')
5. 虚拟环境
虚拟环境就是针对不同的项目,创建出来一个新的python环境,类似于是一个新的python解释器。
class MobileConverter(object):
# 正则规则
regex = "1[3-9]\d{9}"
def to_python(self, value):
# print(type(value))
# 将匹配结果
return value
def to_url(self,):
pass
register_converter(MobileConverter, "mobile")
urlpatterns = [
# 请求路径和视图函数的映射关系,一旦请求路径和某一个path中的路径匹配成功,则调用该path中的视图函数
# path("admin/", admin.site.urls),
# path("timer/", get_timer), # 路径,函数 注意函数不加括号
# path('', index), # 什么都不写就是代表根目录
# 正则和简单分组
# path("articles/2012/12/", article_detail),
# re_path("articles/(\d{4})$", article_archive_by_year),
# re_path("articles/(\d{4})/(\d{1,2})/", article_archive_by_month),
# 有名分组
# re_path("articles/(?P<year>\d{4})/(?P<month>\d{1,2})/", article_archive_by_month),
# 路由分发
# path('home/', include('app01.urls')),
# path('articles/', include('articles.urls')),
# 路由转发器
path("index/<mobile:mobile>", show),
# ******************* 二 视图 ***********************
path("users/", include('users.urls'))
]
"""
请求路径: /articles/2010/12
re.findall("articles/(\d{4})/(\d{1,2})", "/articles/2010/12")
一旦匹配成功:
if 是简单分组:
调用 article_archive_by_month(request, 2010, 12)
elif 是有名分组
调用 article_archive_by_month(request,year=2010, month=12)
"""