路由
路由称为URL(统一资源定位符),是表示可以从互联网上得到的资源位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每一个文件都有唯一的一个路由,用于指出网站文件的路径位置。
1. django路由定义:
在app文件夹内,添加urls.py文件,开发者应将所有属于该app的路由都写入该文件,因为这样更易于管理和区分每个路由地址。 Django Project中的urls.py是将每个app的urls.py统一管理。
工作原理:
1.运行django项目时,django首先到DjangoProject文件夹下的urls.py中找到每个app所定义的路由,生成完整的路由列表。
2.用户在浏览器上访问某个路由地址时,django收到用户的请求信息。
3.django从请求信息中获取路由地址,并在路由表中匹配相应的路由信息,再执行由路由函数所指向的视图函数或视图类,从而完成整个请求响应过程。
Django Project中的urls.py的代码如下:
from django.contrib import admin
from django.urls import path, re_path, include
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', include('index.urls')), # app应用下的urls
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media') # 媒体文件
]
可以看到,首页地址将路由分发给index的urls.py进行处理,所以应当对index中的urls.py编写路由信息。
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
views中的代码
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse('hello world')
路由文件urls.py的路由定义的规则是相对固定的,路由列表由urlpatterns表示,每个列表元素代表一条路由。路由是由django的path函数定义的,函数的第一个参数是路由地址,第二个参数是路由对应的视图处理函数。
2. 路由变量的设置(建议在自己电脑上测试。):
- Django在定义路由时,可以对路由设置变量值。
路由的变量类型有字符类型,整形,slug,uuid
- 字符类型:匹配任何非空字符串,不包含斜杠(默认使用)。
- 整型:匹配自然数。
- slug:可理解为注释等概念,一般为路由的解释性字符。可匹配任何ASCII码字符以及连接符和下划线。
uuid:匹配一个uuid格式的对象,所有字母必须小写。
# index.urls中的代码 from django.urls import path from . import views urlpatterns = [ path('', views.index), path('<year>/<int:month>/<slug:day>', views.index2) # <year>数据类型为string,与<str:year>相同 # <int:month>,数据类型为int,变量名为month # <slug:day>,变量名为day,数据类型为slug ]
# view.index2中的代码 def index2(request, year, month, day): return HttpResponse('hello django ' + str(year) + "-" + str(month) + "-" + str(day))
django支持在路由地址之外设置变量(路由的可选变量),此变量是path函数中的第三个参数。
- 参数只能以字典的形式出现。
- 设置的参数只能在视图函数中读取和使用。
字典的一个键值对代表一个参数,键代表参数名,值代表参数值。
from django.urls import path from . import views urlpatterns = [ path('', views.index), # 添加了path变量的第三个参数 path('data/', views.index3, {'data': '2020/11/02'}), path('<year>/<int:month>/<slug:day>', views.index2) ]
from django.shortcuts import render from django.http import HttpResponse # Create your views here. # 字典中的data键值对被使用 def index3(request, data): return HttpResponse('hello django ' + data)
正则表达式路由的定义,正则表达式路由是由re_path函数定义的
from django.urls import path, re_path from . import views urlpatterns = [ # 正则表达式匹配 re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index4), ] # ?P是固定格式,P必须大写 # <year>是变量名 # [0-9]{4}是正则表达式的匹配模式
def index4(request, year, month): return HttpResponse('hello Django ' + " " + year + "/" + month)
3. 命名空间与路由命名
命名空间
from django.contrib import admin
from django.urls import path, re_path, include
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
# 可以看到include函数中的参数发生了变化
path('index/', include(('index.urls', 'index'), namespace='index')),
path('user/', include(('user.urls', 'user'), namespace='user')),
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
]
路由函数设由参数args与namespace,参数args指向项目应用app下的urls.py文件;若要对设置namespace参数那么args参数必须是一个长度为2的元组,其中第0个元素是指项目应用的urls.py文件,第二个参数可自行命名一般与项目的应用名相同
路由命名
路由命名使用name参数,若路由中使用了include函数,那么没有必要再设置name参数。
from django.urls import path, re_path
from . import views
urlpatterns = [
# 在path login中设置了name值
path('login/', views.login, name='login'),
path('', views.index),
path('data/', views.index3, {'data': '2020/11/02'}, name='data'),
path('<year>/<int:month>/<slug:day>', views.index2, name='date'),
re_path('(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index4),
]
4. 路由的使用方式
在模板中使用路由
# 路由文件 from django.urls import path, re_path from . import views urlpatterns = [ path('', views.index), path('<year>/<month>/<day>', views.index2, name='date'),# 命名路由名字为date ]
# 视图文件 from django.shortcuts import render from django.http import HttpResponse # Create your views here. def index(request): return render(request, 'index.html') def index2(request, year, month, day): return HttpResponse('hello django ' + str(year) + "-" + str(month) + "-" + str(day))
<!-- html文件 --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> <h4>hello templates</h4> <!--date代表名字为date的路由,date后面紧跟参数,空格隔开--> <a href="{%url 'date' '2020' '10' '10' %}">link</a> <!--若项目应用设有命名空间,则应在命名路由前添加命名空间namespace--> <a href="{% url 'guest:index' %}">link2</a> </body> </html>
- 若路由地址存在变量,则模板语法需要设置相应的参数值,参数之间空格隔开。
- 若路由地址不存在变量,则不需设置参数值,设置路由名称即可。
- 若地址存在变量,但参数数量与url参数不同,django报错。
反向解析reverse与resolve
reverse:通过路由命名或可调用视图对象来生成路由地址。
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
- viewname:代表路由命名或可调用路由对象,一般以路由命名name来生成路由地址。
- urlconf:设置反向解析的URLconf模块。
- args:以列表方式传递路由地址变量,列表元素顺序和数量应与路由地址变量的顺序和数量相同。
- kwargs:以字典方式传递路由变量。
- current_app:提示当前正在执行的视图所在的项目应用,几乎无用。
resolve:通过路由地址来获得路由对象信息。
def resolve(path, urlconf=None):
- path:路由地址。
- urlconf:设置反向解析的URLconf模块。
# 自己运行一遍
# view代码 from django.shortcuts import render, reverse from django.http import HttpResponse from django.urls import resolve # Create your views here. def index(request): kwargs = {'name': 'ronie'} args = ['ronie'] print(reverse('guest:name', args=args)) # args与kwargs参数不能同时设置 print(reverse('guest:name', kwargs=kwargs)) return HttpResponse(reverse('guest:name', args=args)) def name(request, name_): args = ['ronie'] result = resolve(reverse('guest:name', args=args)) print('kwargs: ', result.kwargs) print('url_name: ', result.url_name) print('namespace: ', result.namespace) print('view_name: ', result.view_name) print('app_name: ', result.app_name) return HttpResponse(name_)
# urls.py代码 from django.urls import path, re_path from . import views urlpatterns = [ path('', views.index, name='index'),# 主页 path('<name_>', views.name, name='name'), ]
5. 路由重定向:
重定向:建议百度。
django网页重定向的方式有两种
路由重定向:使用django视图类RedirectView实现,默认用HTTP的get请求。
# urls.py文件 from django.urls import path, re_path from . import views from django.views.generic import RedirectView urlpatterns = [ path('', views.index, name='index'), path('<name_>', views.name, name='name'), # 在路由中重定向 path('turnTo/', RedirectView.as_view(url='/index'), name='turnTo'), ]
自定义视图重定向:自定义视图的响应状态设置重定向。
# view文件 from django.shortcuts import render, reverse, redirect from django.http import HttpResponse from django.urls import resolve # Create your views here. def name(request, name_): args = ['ronie'] result = resolve(reverse('guest:name', args=args)) print('kwargs: ', result.kwargs) print('url_name: ', result.url_name) print('namespace: ', result.namespace) print('view_name: ', result.view_name) print('app_name: ', result.app_name) return HttpResponse(name_) # 通过重定向函数redirect重定向 def turnTo(request): return redirect(reverse('guest:name', args=['ronie'])) # redirect函数
Comments | NOTHING