Django框架视图与路由(一)
一、Django框架视图基础
我们可以把Django框架里的视图想象成餐厅里的服务员,帮助我们理解它的作用和工作方式。
视图就像服务员
在餐厅里,顾客(用户)进入餐厅(访问网站)后,会提出各种需求(发送请求),比如点菜(获取特定信息)。这时,服务员(视图)就会出现,接收顾客的需求(HttpRequest对象)。服务员会把顾客的需求传达给厨房(模型层和模板层),让厨房准备相应的菜品(处理数据)。最后,服务员把准备好的菜品(响应内容)端给顾客(返回HttpResponse对象)。
视图的工作流程
- 接收请求:当用户在浏览器中输入网址或者进行操作时,就相当于顾客向服务员提出需求。Django会创建一个包含请求信息的HttpRequest对象,就像服务员记录顾客的需求一样。
- 处理请求:视图接收到HttpRequest对象后,会根据请求的内容进行相应的处理。这可能包括查询数据库(从厨房获取食材)、调用其他函数(使用厨房的工具)等,以生成需要返回给用户的内容。
- 返回响应:处理完请求后,视图会返回一个HttpResponse对象,就像服务员把准备好的菜品端给顾客一样。这个对象包含了要显示给用户的内容,比如网页的HTML代码、图片等。
视图的分类
视图有两种类型,就像餐厅里有不同类型的服务员:
- 基于函数的视图(FBV):就像普通的服务员,按照固定的流程为顾客服务。每次顾客提出需求,服务员都会按照相同的步骤处理。
- 基于类的视图(CBV):就像专业的服务员,根据不同的情况提供不同的服务。比如,对于不同类型的顾客(不同的请求方法,如GET、POST),服务员会采用不同的服务方式。
示例说明
假设我们有一个简单的餐厅,顾客可以询问当前的时间。这时,服务员(视图)会看一下手表(获取当前时间),然后告诉顾客现在的时间(返回包含时间信息的响应)。以下是对应的代码示例:
from django.http import HttpResponse
import datetime
def current_datetime(request):
# 获取当前时间
now = datetime.datetime.now()
# 生成包含时间信息的HTML代码
html = "<html><body>It is now %s.</body></html>" % now
# 返回响应
return HttpResponse(html)
在这个示例中,current_datetime
函数就是一个视图,它接收顾客的请求(request
参数),获取当前时间,生成包含时间信息的HTML代码,并返回一个HttpResponse对象给顾客。
二、URL路由配置
1.URL路由基础
- 对于高质量 Web 应用,简洁优雅的 URL 设计至关重要。Django 框架让设计人员可自由设计 URL 模式,不受框架约束。
- URL 路由是 Web 服务入口。用户通过浏览器发送请求,会解析到指定 URL 地址,从而获得服务器响应,这是基本流程。
- 在 Django 项目中,URL 路由配置通过
urls.py
文件完成。一个项目含多个 App 时会有多个urls.py
文件,但不能放在同一目录。一般在项目根目录设根路由urls.py
,每个 App 下再定义各自的urls.py
,这是先进的解耦模式。 - 总之,URL 路由是路径与视图函数的对应关系,起中间媒介作用,原理见图
Django的路由系统工作流程
客户端用户的http请求:图的左侧是客户端用户发出的http请求,这些请求通过箭头指向Django路由系统。
- Django路由系统:位于图的右侧,是整个流程的核心部分。它接收来自客户端的http请求。
- URL映射:在Django路由系统内部,包含了URL映射机制,图中列出了URL1、URL2、URL3等多个URL。这些URL将用户的http请求映射到相应的View处理函数。
- View处理函数:每个URL对应一个View处理函数,这些函数在接收到请求后进行相应的处理,并最终返回一个HttpResponse对象,作为对客户端请求的响应。
from django.contrib import admin # 调用模块导入对象,自带的管理员模块
from django.urls import path # 调用django.urls导入path,这是一个负责URL路由配置的模块
urlpatterns = [
path("admin/", admin.site.urls), # 定义了一个数组,通过path定义具体的路径配置信息
path('hello/', views.hello),
...
]
2.Django如何处理请求
- 请求接收:用户发起HTTP请求,由项目的
wsgi.py
接收,传递给URL解析器。 - URL路由:解析器加载
urls.py
,按顺序匹配urlpatterns
中的条目,找到匹配的URL后,将请求派发给对应的视图函数或类视图。 - 中间件处理:请求在到达视图前,按
settings.py
中MIDDLEWARE
顺序经过中间件,中间件可执行多种操作,如修改请求、处理异常等。 - 视图处理:视图接收
HttpRequest
对象,处理业务逻辑,查询数据库等,最终返回HttpResponse
对象,可能会使用模板引擎渲染模板。 - 模板渲染:若视图使用模板,会加载并渲染模板,将数据插入模板标记,生成的内容作为响应的一部分。
- 响应处理:响应在返回用户前,再次经过中间件,中间件可对其检查、修改。
- 返回响应:处理后的
HttpResponse
对象经WSGI层返回给用户浏览器。 - 异常处理:视图或中间件抛出异常时,异常中间件捕获异常,开发时
DEBUG=True
可显示详细错误,生产环境则配置友好错误页面 。
3.PATH路径转换器
在Django中,PATH路径转换器是URL路由里用于匹配和捕获URL特定模式,并将匹配的路径段传递给视图函数的工具 。
内置PATH路径转换器
Django提供了多种内置的PATH路径转换器 :
- str:匹配除斜杠
/
以外的任何非空字符串,若未专门指定转换器,此为默认使用的类型。例如path('v1/users/<str:username>', views.py)
可匹配v1/users/zyyy
。 - int:匹配0和正整数,返回
int
类型。如path('page/<int:page>', views.py)
能匹配/page/100
。 - slug:匹配字母、数字、下划线或连字符组成的字符串,可理解为url最后的注释、后缀等解释性字符 。例如
path('detail/<slug:sl>', views.py)
可匹配detail/this-is-django
。 - uuid:匹配一个uuid格式的对象,需使用破折号且所有字母小写,例如
075194d3 - 6885 - 417e - a8a8 - 6c931e272f00
,返回一个UUID对象。 - path:匹配任何非空字符串,包括路径分隔符
/
。比如path('v1/users/<path:ph>', views.py)
可匹配/v1/goods/a/b/c
。
自定义PATH路径转换器
在某些复杂需求下,可自定义路径转换器 :
- 创建自定义路径转换器:例如创建一个匹配大写字母字符串的路径转换器,在
blog/converters.py
中编写如下代码:
class UppercaseConverter:
# 定义正则表达式,仅匹配大写字母
regex = '[A-Z]+'
# 将路径段字符串转换为Python对象(可选,直接返回即可)
def to_python(self, value):
return value
# 将Python对象转换为URL使用的字符串(可选,直接返回即可)
def to_url(self, value):
return value
- 注册自定义路径转换器:在
urls.py
文件中导入并注册:
from django.urls import register_converter, path
from blog.converters import UppercaseConverter
# 注册自定义路径转换器
register_converter(UppercaseConverter, 'uppercase')
# 定义一个视图函数作为示例
from django.http import HttpResponse
def greet(request, name):
return HttpResponse(f"Hello, {name}!")
# 使用自定义路径转换器
urlpatterns = [
path('blog/greet/<uppercase:name>/', greet),
]
启动服务器后,http://127.0.0.1:8000/blog/greet/HELLO/
可匹配成功,返回“Hello, HELLO!”;http://127.0.0.1:8000/blog/greet/hello/
匹配失败,返回404页面 。
4.使用正则表达式
在Django中,使用正则表达式可实现复杂的URL模式匹配,主要通过re_path
函数来完成,其提供了基于正则表达式的强大匹配能力,能处理更复杂的URL模式需求,通过自定义正则表达式匹配,可定义灵活且精确的路由规则 。
re_path
基本语法
re_path
的语法格式如下 :
from django.urls import re_path
urlpatterns = [
re_path(r'^pattern$', view_function, name='route_name'),
]
其中:
r’^pattern$’
是正则表达式,用于匹配URL 。^
表示匹配字符串的开始位置,$
表示匹配字符串的结束位置,确保整个URL与正则表达式完全匹配 。view_function
是对应的视图函数,当URL匹配成功时,Django会调用该视图函数处理请求 。name
是路由的名称(可选),可用于反向解析URL 。
示例
- 匹配用户名的路由:假设要求用户名只能包含字母、数字或下划线,长度为3到15个字符。示例代码如下 :
# urls.py
from django.urls import re_path
from django.http import HttpResponse
# 示例视图函数
def user_profile(request, username):
return HttpResponse(f"User profile: {username}")
# 使用re_path定义路由
urlpatterns = [
re_path(r'^profile/(?P<username>[a-zA-Z0-9_]{3,15})/$', user_profile),
]
测试时,访问http://127.0.0.1:8000/profile/john_doe/
,会返回User profile: john_doe
;访问http://127.0.0.1:8000/profile/john - doe/
,匹配失败,返回404页面 。这里(?P<username>[a-zA-Z0-9_]{3,15})
是一个命名分组,?P<username>
指定组名为username
,[a-zA-Z0-9_]{3,15}
表示匹配由字母、数字、下划线组成,长度在3到15个字符之间的字符串,并将匹配到的内容作为关键字参数传递给user_profile
视图函数 。
- 匹配日期格式:假设要匹配URL中的日期格式,并将其解析为视图函数的参数。示例代码如下 :
# urls.py
from django.urls import re_path
from django.http import HttpResponse
from datetime import datetime
# 示例视图函数
def event_view(request, year, month, day):
date = f"{year}-{month}-{day}"
return HttpResponse(f"Event date: {date}")
# 使用re_path定义路由
urlpatterns = [
re_path(r'^event/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', event_view),
]
测试时,访问http://127.0.0.1:8000/event/2024/11/17/
,返回Event date: 2024 - 11 - 17
;访问http://127.0.0.1:8000/event/24/11/17/
,匹配失败。这里(?P<year>\d{4})
、(?P<month>\d{2})
和(?P<day>\d{2})
分别匹配4位数字的年份、2位数字的月份和2位数字的日期,并作为关键字参数传递给event_view
视图函数 。
- 结合正则表达式实现高级功能
- 匹配十六进制颜色代码:十六进制颜色代码格式为
#RRGGBB
或#RGB
,示例代码如下 :
- 匹配十六进制颜色代码:十六进制颜色代码格式为
# urls.py
from django.urls import re_path
from django.http import HttpResponse
# 示例视图函数
def color_view(request, color):
return HttpResponse(f"Color: #{color}")
# 使用re_path定义路由
urlpatterns = [
re_path(r'^color/(?P<color>[A - Fa - f0 - 9]{6}|[A - Fa - f0 - 9]{3})/$', color_view),
]
测试时,访问http://127.0.0.1:8000/color/FF5733/
,返回Color: #FF5733
;访问http://127.0.0.1:8000/color/123/
,返回Color: #123
;访问http://127.0.0.1:8000/color/GG5733/
,匹配失败 。
匹配自定义Slug格式:假设自定义Slug格式由字母、数字、连字符组成,示例代码如下 :
# urls.py
from django.urls import re_path
from django.http import HttpResponse
# 示例视图函数
def article_view(request, slug):
return HttpResponse(f"Article: {slug}")
# 使用re_path定义路由
urlpatterns = [
re_path(r'^article/(?P<slug>[a-zA-Z0-9 -]+)/$', article_view),
]
测试时,访问http://127.0.0.1:8000/article/django - tutorial/
,返回Article: django - tutorial
;访问http://127.0.0.1:8000/article/django_tutorial/
,匹配失败 。
与基于path
的路径转换器相比,re_path
提供了更高的灵活性,适用于复杂的URL模式需求 。
5.URLconf在什么上查找
URLconf在请求的URL上查找,将其当作一个普通的Python字符串,查找时不包括GET和POST参数以及域名 。例如,对于请求地址
http://www.example.com/myapp/
,URLconf查找的是myapp/
;对于请求地址http://www.example.com/myapp/?page=3
,URLconf查找的同样是myapp/
。通常情况下,Django确定要使用的根URLconf模块,一般是
settings
中ROOT_URLCONF
设置的值 。但如果传入的HttpRequest
对象具有urlconf
属性(由中间件设置),则其值将用于代替ROOT_URLCONF
设置 。接着,Django加载该Python模块并查找变量urlpatterns
,它是django.conf.urls.url()
实例(在Django 2.x+版本中通常是django.urls.path()
或django.urls.re_path()
实例)的一个Python列表 。Django按顺序遍历每个URL模式,并在与请求的URL匹配的第一个模式停下来 。
6.指定视图参数的默认值
在Django中指定视图参数默认值是一个方便的技巧,当URL没有为视图函数的参数提供值时,将使用默认值。以下通过示例说明:
- 示例一:假设在urls.py中有如下配置:
from django.conf.urls import url
from. import views
urlpatterns = (
url(r'^blog/$', views.page),
url(r'^blog/page(?P<num>(0-9)+)/$', views.page),
)
在视图函数(如blog/views.py)中定义:
def page(request, num="1"):
# Output the appropriate page of blog entries, according to num.
#...
pass
这里两个URL表达式都指向views.page
视图 。第一个表达式没有传递任何参数,若匹配到第一个样式,page()
函数将会对参数num
使用默认值"1"
;如果第二个表达式匹配成功,page()
函数将使用正则表达式传递过来的num
的值 。注意设置默认参数值为字符串"1"
,因为捕捉给num
的值总是字符串 。
- 示例二:如果在urls.py中有:
from django.urls import path
from. import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page),
]
视图函数为:
def page(request, num = 1):
pass
此时第一个模式不会从URL中捕获任何值,如果第一个模式匹配,page()
函数将使用num
参数的默认值1
;如果第二个模式匹配,page()
将使用捕获的num
值 。
- 示例三:构建Django项目时,在urls.py 中的路径为
path('device_id/<str:device_id>/readings/<int:num_readings>, views.results, name='results')
,若想在用户未输入读数时避免404,可在视图中指定默认读数 。视图函数定义为def results(request, device_id="", readings=10):
,同时使用re_path
以便用正则表达式声明num_readings
是可选的 ,如urlpatterns = ( re_path( 'device_id/(?P<device_id>\w+)/readings/(?P<num_readings>\d+)?',views.results,name='results' ),)
。
综上,通过在视图函数中直接为参数指定默认值,结合URL的匹配规则,可实现视图参数默认值的设定 。
7.包含其他的URLconf模块
在Django中,将每个应用程序设置一个URLConf模块,并将其包含在根URLConf模块中,是一种良好的开发实践 。这样做有助于实现代码的模块化和可维护性,特别是在大型项目中。具体步骤和要点如下:
在根URLConf模块中包含应用的URLConf模块:在根urls.py
文件中,使用include
函数来包含其他应用的URLConf模块。例如:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('books.urls')),
]
上述代码中,path('', include('books.urls'))
表示Django会在books/urls.py
文件中搜索URL模式 。
应用的URLConf模块配置:以books/urls.py
为例,它可以定义该应用特有的URL模式,示例代码如下:
from django.urls import path
from. import views
urlpatterns = [
path('books/<int:pk>/', views.book_detail),
path('books/<str:genre>/', views.books_by_genre),
path('books/', views.book_index),
]
当请求的URL与这些模式匹配时,会调用相应的视图函数。比如,/books/crime/
的URL请求将与path('books/<str:genre>/', views.books_by_genre)
匹配,Django会调用函数views.books_by_genre(request, genre = “crime”)
;/books/25/
的URL请求将匹配path('books/<int:pk>/', views.book_detail)
,Django将调用函数views.book_detail(request, pk =25)
。
注意事项:
根URLConf模块设置:通常在settings.py
文件中通过ROOT_URLCONF
指定根级url的配置,默认情况下,它被设置为项目的urls.py
。根urls.py
中针对应用配置的URL名称,是该应用所有URL的总路径 。
正则表达式相关:在编写URL模式时,若使用正则表达式,要注意一些规则。例如,若要从url中捕获一个值,需要在它周围设置一对圆括号;不需要添加前导反斜杠;每个正则表达式前面的r
表示字符串不转义;urlpatterns中的每个正则表达式在第一次访问时被编译,可提高系统速度。另外,指向include()
的正则表达式通常不包含$
(字符串结尾匹配符),但会包含一个斜杆。每当Django遇到include()
时,它将截断匹配的URL,并把剩余的字符串发往被包含的URLconf作进一步处理 。
参数传递:被包含的URLconf会接收来自父URLconfs的被捕获的参数,并传递给其中的视图函数 。例如在root urls.py
中有(r'^(?P<username>\w+)/blog/', include('foo.urls.blog'))
,在foo/urls/blog.py
中的视图函数就能接收到username
这个参数 。
8.传递额外参数给视图函数
在Django中传递额外参数给视图函数,常见方式如下:
使用path()
函数捕获URL参数:可以在path()
函数的路由中使用尖括号捕获URL中的部分作为参数传递给视图函数。例如:
# urls.py
from django.urls import path
from.views import my_view
urlpatterns = [
path('example/<str:extra_param>/', my_view, name='my_view'),
]
# views.py
from django.http import HttpResponse
def my_view(request, extra_param):
return HttpResponse(f'This is my view with extra_param: {extra_param}')
当访问/example/some_value/
时,some_value
会作为extra_param
的值传递给my_view
函数 。
传递多个参数:在URL中使用多个捕获组来传递多个参数。例如:
# urls.py
from django.urls import path
from.views import my_view
urlpatterns = [
path('example/<str:extra_param>/<int:number_param>/', my_view, name='my_view'),
]
# views.py
from django.http import HttpResponse
def my_view(request, extra_param, number_param):
return HttpResponse(f'This is my view with extra_param: {extra_param} and number_param: {number_param}')
访问/example/some_value/42/
时,some_value
作为extra_param
的值,42
作为number_param
的值传递给my_view
函数 。
提供默认参数:为避免客户端请求因缺少参数导致404错误,可在URL配置中为参数提供默认值。例如:
# urls.py
from django.urls import path
from.views import my_view
urlpatterns = [
path('example/<str:extra_param>/<int:number_param>/', my_view, name='my_view'),
path('example/', my_view, {'extra_param': 'default_value', 'number_param': 0}, name='my_view_default'),
]
# views.py
from django.http import HttpResponse
def my_view(request, extra_param='default_value', number_param=0):
return HttpResponse(f'This is my view with extra_param: {extra_param} and number_param: {number_param}')
此时访问http://mysite.com/example/
,视图函数将使用默认值 。
使用字典传递额外参数:在path()
函数中包含Python字典类型的参数,再传递给视图函数 。例如:
# urls.py
from django.urls import path
from.views import my_view
urlpatterns = [
path('example/', my_view, {'key': 'value'}, name='my_view'),
]
# views.py
from django.http import HttpResponse
def my_view(request, key):
return HttpResponse(f'This is my view with key: {key}')
通过GET请求传递参数:在URL中通过?参数名字=value&参数名字=value
的形式传递多个参数,后端通过request.GET.get('参数名字')
获取传递的参数。例如:
# views.py
def div_page(request):
page_num = request.GET.get('page')
content = request.GET.get('content')
print(content)
print(page_num)
return HttpResponse(int(page_num))
URL为http://127.0.0.1:8000/page/?page=5&content=3
。这种方式后端无需在函数中定义额外参数,较为灵活 。
使用正则表达式传递参数:
- 无名分组:通过未命名的正则表达式组捕获参数,按顺序作为位置参数传递给视图函数。例如:
# urls.py
from django.urls import re_path
from.views import my_view
urlpatterns = [
re_path(r'^example/(\d+)/(\w+)/', my_view),
]
# views.py
from django.http import HttpResponse
def my_view(request, param1, param2):
return HttpResponse(f'param1: {param1}, param2: {param2}')
- **有名分组**:使用命名的正则表达式组`(?P<name>pattern)`捕获参数,按关键字参数传递给视图函数。例如:
# urls.py
from django.urls import re_path
from.views import my_view
urlpatterns = [
re_path(r'^example/(?P<param1>\d+)/(?P<param2>\w+)/', my_view),
]
# views.py
from django.http import HttpResponse
def my_view(request, param1, param2):
return HttpResponse(f'param1: {param1}, param2: {param2}')
需要注意,当混杂命名正则和未命名正则两种样式时,未命名的组会被忽略,只有命名的组才会传递给视图函数 。
9.反向解析
在Django中,反向解析指通过一些方法得到一个结果,该结果可以访问到对应的url并触发视图函数运行 。
反向解析的用途
在软件开发初期,url地址路径设计可能不完善,后期若需调整,若项目中多处使用该路径,直接修改路径会很繁琐。通过反向解析,在编写 url(regex, view, kwargs=None, name=None)
时,利用参数 name
为url路径起别名,项目中通过别名获取路径。日后路径变化,只要别名与路径对应关系不变,就无需修改使用该路径的各处代码 。
反向解析的实现方式
- 模板中超链接的解析:在模板中使用
{% url '别名' %}
的方式进行反向解析。例如在index.html
中,<a href="{% url 'test_app:test2' %}">反向解析fan2</a>
,这里test_app
是命名空间,test2
是路由别名。如果路由配置了命名空间,格式通常为命名空间:别名
。 - 视图函数中的重定向:在视图函数中,从
django.urls
引入reverse
函数,使用redirect(reverse('别名'))
进行反向解析重定向。如def redirect_view(request): return redirect('test_app:test2')
。若路由存在参数,传递方式为redirect(reverse('别名', args=(参数值,)))
(位置参数)或redirect(reverse('别名', kwargs={'参数名':参数值}))
(关键字参数) 。 - 带参数的反向解析:当路由存在分组(无名分组和有名分组)时,反向解析需传递相应参数。例如对于无名分组
url(r'^aritcle/(\d+)/$',views.article,name='article_page')
,反向解析时后端可使用reverse('article_page', args=(1,))
;对于有名分组url(r'^user/(?P<uid>\d+)/$',views.article,name='user_page')
,后端反向解析写法可以是reverse('user_page', kwargs={'uid': 1})
。前端写法类似,如<a href="{% url 'user_page' uid=1 %}">链接</a>
。
反向解析的相关函数
reverse
:通过路由命名空间或可调用视图对象生成路由地址。有viewname
(路由命名或可调用视图对象)、urlconf
(设置反向解析的URLconf模块,默认使用主路由)、args
(以列表方式传递路由地址变量)、kwargs
(以字典方式传递路由地址变量)、current_app
(提示当前正在执行的视图所在的项目应用)等参数 。resolve
:通过路由地址获取路由对象信息,有path
(代表路由地址)、urlconf
(设置反向解析的URLconf模块,默认使用主路由)两个参数,返回的路由对象有func
(视图函数或视图类对象)、args
(以列表格式获取路由变量信息)、kwargs
(以字典格式获取路由变量信息)、url_name
(获取路由命名name)等内置函数方法来获取具体路由信息 。
10.命名空间
在Django中,命名空间(Namespace)是表示标识符可见范围的概念,它能有效避免因不同应用中定义相同 name
而导致的URL反解错误 。
由于 name
没有作用域,Django反解URL时会在项目全局顺序搜索,一旦找到第一个 name
指定的URL就立即返回。所以在开发项目时,若不同应用的 urls
中不小心定义了相同的 name
,可能致使URL反解出错。为解决此问题,引入了命名空间 。
在Django中,include
函数可用于设置命名空间,其形式如 include(module(, namespace=None, app_name=None ))
、include(pattern_list)
、include((pattern_list, app_namespace, instance_namespace))
,其中 app_namespace
即应用命名空间,instance_namespace
即实例命名空间 。带有命名空间的URL组成方式为 “命名空间:名称”,以 :
为分隔符,且命名空间URL支持嵌套,例如 “foo:bar:whiz
” 。
解析命名空间URL时,假设要解析 “myapp:index
” 这样的命名空间URL :
- django会查找符合条件(此例中为
myapp
)的应用命名空间,返回一个符合条件的实例命名空间列表 。 - 若有当前应用实例被定义,即用于渲染的模版中的
Context
或者RequestContext
中的current_app
属性被设置,那么该值就是当前应用实例,使用该实例 。 - 若没有当前应用实例被定义,会查找一个默认应用实例,该实例命名空间的名字与应用命名空间的名称一样。
- 若没有默认应用实例,则会按照声明次序,返回最后一个被声明的实例命名空间 。
- 若第一步没有匹配条件的应用命名空间,django会直接去查找匹配的实例命名空间 。
例如在项目的 urls.py
中,可通过如下方式设置命名空间:
from django.urls import path
from myapp import views
from django.conf.urls.static import static
from django.conf import settings
from django.conf.urls import re_path,include
from myapp import *
from myapp02 import *
urlpatterns = [
# path('admin/', admin.site.urls),
path('hello/',views.hello),
path('login/',views.login,name = 'Log'),
re_path(r"^myapp/",include(("myapp.urls","myapp"))), #这里使用元组设置命名空间为myapp
re_path(r"^myapp02/",include(("myapp02.urls","myapp02"))),
] + static(settings.STATIC_URL,document_root=settings.STATIC_ROOT)
在应用的 urls.py
中,例如 app1 urls.py
:
# !/usr/bin/env python
# -*- coding:utf-8 -*-
from django.conf.urls import url
from myapp import views
from django.urls import re_path
urlpatterns = [
re_path(r'^index/',views.index,name='index'),
url(r'^hello/([0-9]{4})/$', views.year_archive,name='y'),
url(r'^hello/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^hello/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
在视图函数中,如 app1 views.py
,可通过命名空间反向解析URL :
from django.shortcuts import render
from django.http import HttpResponse
from django.urls import reverse
# Create your views here.
# request 是固定写法
def index(request):
return HttpResponse(reverse("myapp:index"))
在模板中使用 {% url %}
标签访问时,若存在多级命名空间,如在 portfolio_menu.urls
、store.urls
、product.urls
分别设置了命名空间 portfolio
、store
、product
,且 product.urls
中有视图的 name
为 list
,理论上可通过类似 {% url portfolio:store:product:list %}
的方式访问,但需注意配置正确,避免出现如 django.core.exceptions.ImproperlyConfigured
等错误 。