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

Django 项目中应用的目录结构

接下来在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)

代码都完成之后,重启服务,然后在浏览器中访问,内容如下

Django 组织URL后访问视图

现在我们在 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)
]

然后重启服务,在浏览器中访问,结果如下

Django 访问视图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 函数来完成正则表达式的匹配。 如果对于正则表达式不清楚的可以查看我们的 正则表达式教程

添加代码之后,然后重启服务,在浏览器中访问。结果如下

Django 给视图传参访问示例

需要注意的是,参数的顺序在这里很重要。假设我们想要一年中某一个月的文章列表,让我们添加一个 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)
]

重启服务,访问结果如下

Django 视图参数顺序

但这里有个问题,如果将参数对换,则不会得到相同的结果。例如,将 year 和 month的位置互换

def articles(request, year, month):
    text = "<h1>欢迎访问迹忆客 !</h1><p>获取 %s/%s 的文章</p>" % (year, month)
    return HttpResponse(text)

结果如下

Django 视图参数顺序互换

这很明显是不对的。因此为了避免这种情况,我们使用正则表达式中的命名捕获,修改后的路由代码如下

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的位置如何,都不会影响结果。

查看笔记

扫码一下
查看教程更方便