Django 路由
在前面的章节中我们介绍了视图,本章节介绍Django 路由。在视图一章对路由的知识也稍微有所涉及,这里我们详细介绍一下Django 路由。
Django 有自己的 URL 映射方式,我们项目中所有的路由是在 urls.py 文件(firstProject/urls.py) 中来完成的。urls.py 文件最初代码如下
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
当用户对 Web 应用程序上的某个页面发出请求时,Django 控制器会通过 urls.py 文件查找相应的视图,然后返回 HTML 响应或 404 not found 错误(如果未找到)。在 urls.py 中,最重要的是“urlpatterns”元组。它是定义 URL 和视图之间的映射的地方。映射是 URL 模式中的元组,例如在视图一节中新建的视图和路由,路由代码如下
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.hello, name='hello')
]
控制器将 URL /hello 映射到 firstProject/views.py 文件中的 hello
视图。正如上面所看到的,一个路由映射包含三部分
- 匹配模式 - 与要解析和映射的 URL 匹配的字符串。也可以是一个正则表达式,可以用 re_path 函数来使用正则表达式,这在需要给视图传参的时候是很有用的。
- 视图所在的路径
- 名称 - 为了执行 URL 反转,需要使用命名 URL 模式,如上面的示例中所做的那样。
管理你的URL
到目前为止,我们已经在“firstProject/url.py”文件中创建了 URL,但是正如前面关于 Django 和创建应用程序所述,该项目最好的一点就是能够在不同的项目中对代码进行复用。如果我们将所有 URL 保存在“firstProject/urls.py”文件中,那么很容易就能看到问题所在。因此,最好的方法是为每个应用程序创建一个“urls.py”并将其包含在我们的主要项目 urls.py 文件中
首先让我们在项目 firstProject 中新建一个应用 app
$ python3 manage.py startapp app
命令执行成功之后,我们会看到生成了一个具有下面目录结构的应用
$ tree app
app
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
接下来在app中新建urls.py 文件,添加一个路由,内容如下
from django.urls import path
from . import views
urlpatterns = [
path('hello/', views.hello)
]
然后我们修改 firstProject 主项目中的urls.py,引入 app中的路由,代码如下
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('app/', include('app.urls'))
]
接着我们在 app 的 views.py 中添加 hello 视图
from django.http import HttpResponse
def hello(request):
text = "<h1>欢迎访问迹忆客 !</h1><p>这是 app 应用中的视图</p>"
return HttpResponse(text)
代码都完成之后,重启服务,然后在浏览器中访问,内容如下
现在我们在 app中添加另一个视图 visit
def visit(request):
text = "<h1>欢迎访问迹忆客 !</h1><p>这是 app 应用中的 visit 视图</p>"
return HttpResponse(text)
然后在 app urls.py 中添加一个路由
from django.urls import path
from . import views
urlpatterns = [
path('hello/', views.hello),
path('visit/', views.visit)
]
然后重启服务,在浏览器中访问,结果如下
给视图传参
现在我们知道如何创建路由映射URL,如何对它们进行管理,现在让我们看看如何给视图传参。
传递参数是通过使用URL 模式中的正则表达式捕获来完成的。首先让我们在 app 的 views.py 中新建一个视图 article
from django.http import HttpResponse
def hello(request):
text = "<h1>欢迎访问迹忆客 !</h1><p>这是 app 应用中的视图</p>"
return HttpResponse(text)
def article(request, articleNumber):
text = "<h1>欢迎访问迹忆客 !</h1><p>你现在访问的文章编号为:%s</p>" % articleNumber
return HttpResponse(text)
然后在 app urls.py 中添加一个路由
from django.urls import path, re_path
from . import views
urlpatterns = [
path('hello/', views.hello),
path('visit/', views.visit),
re_path(r'article/(\w+)', views.article)
]
需要注意的是,上面我们说过,传递参数要使用正则表达式捕获来完成,因此这里需要通过使用 re_path 函数来完成正则表达式的匹配。 如果对于正则表达式不清楚的可以查看我们的 正则表达式教程。
添加代码之后,然后重启服务,在浏览器中访问。结果如下
需要注意的是,参数的顺序在这里很重要。假设我们想要一年中某一个月的文章列表,让我们添加一个 viewArticles 视图。
from django.http import HttpResponse
def hello(request):
text = "<h1>欢迎访问迹忆客 !</h1><p>这是 app 应用中的视图</p>"
return HttpResponse(text)
def article(request, articleNumber):
text = "<h1>欢迎访问迹忆客 !</h1><p>你现在访问的文章编号为:%s</p>" % articleNumber
return HttpResponse(text)
def articles(request, month, year):
text = "<h1>欢迎访问迹忆客 !</h1><p>获取 %s/%s 的文章</p>" % (year, month)
return HttpResponse(text)
然后再添加一条路由,代码如下
from django.urls import path, re_path
from . import views
urlpatterns = [
path('hello/', views.hello),
path('visit/', views.visit),
re_path(r'article/(\w+)', views.article),
re_path(r'articles/(\d{2})/(\d{4})', views.articles)
]
重启服务,访问结果如下
但这里有个问题,如果将参数对换,则不会得到相同的结果。例如,将 year 和 month的位置互换
def articles(request, year, month):
text = "<h1>欢迎访问迹忆客 !</h1><p>获取 %s/%s 的文章</p>" % (year, month)
return HttpResponse(text)
结果如下
这很明显是不对的。因此为了避免这种情况,我们使用正则表达式中的命名捕获,修改后的路由代码如下
from django.urls import path, re_path
from . import views
urlpatterns = [
path('hello/', views.hello),
path('visit/', views.visit),
re_path(r'article/(\w+)', views.article),
re_path(r'articles/(?P<month>\d{2})/(?P<year>\d{4})', views.articles)
]
这样,不论year和month的位置如何,都不会影响结果。