路由配置
-
主路由配置
-
setting.py 中 ROOT_URLCONF 指定了主路由配置列表 urlpatterns 的文件位置
- 例如:ROOT_URLCONF = 'MyDjango.urls'
- 指定主路由配置列表 urlpatterns 文件位置在 MyDjango 文件夹下的 urls.py 文件
-
MyDjango 的主路由配置 urls.py 文件
- path() 函数参数:
- route: 字符串类型,匹配的请求路径
- views: 指定路径所对应的视图处理函数名称,不要带()
- name: 为地址起别名,在模板中地址反向解析# MyDjango/urls.py 主路由文件 from django.contrib import admin # 导入admin功能模块 from django.urls import path, include # 导入URL编写模块 # 整个项目的URL集合,每个元素代表一条URL信息 urlpatterns = [ # 设定admin的URL。'admin/' 代表127.0.0.1:8000/admin 地址信息,admin后面的斜杠是路径分隔符; # admin.site.urls 是URL的处理函数,也成为了视图函数 path('admin/', admin.site.urls), # URL为空,代表为网站的域名,即 127.0.0.1:8000,通常是网站的首页 # include将该URL分发给index的urls.py处理 path('', include('index.urls')), path('', include('bookstore.urls')), path('', include('lx_url.urls')), ]
-
-
路由配置 - path - 转换器
转换器类型 作用 样例 str 匹配除了'/'之外的费控字符串 "v1/users/str:username"匹配/v1/users/root int 匹配0或任何正整数。返回一个int "page/int:page"匹配/page/100 slug 匹配任意由ASCII字母或数字以及连字符和下划线组成的段标签 "detail/slug:sl"匹配/detail/this-is-django path 匹配非空字段,包括路径分隔符'/' "v1/users/path:ph"匹配/v1/users/a/b/c - re_path: 使用正则表达式匹配url
- ?P: 固定格式
: 变量命名的编写规则 - [0-9]{1,2}: 正则表达式的匹配模式, 代表变量的长度为1或2, 只允许取0-9的值
- 浏览器访问: http://127.0.0.1:8000/operation/{num1}}/{op}}/{num2}, num1和num2为1或2位正整数才会分发到re_path路由,否则会分发到path路由
# app路由:lx_url/urls.py 文件 from django.urls import path, re_path from . import views urlpatterns = [ re_path(r'operation/(?P<num1>[0-9]{1,2})/(?P<op>w+)/(?P<num2>[0-9]{1,2})$', views.re_operation), path('operation/<int:num1>/<str:op>/<int:num2>', views.operation), ] # app视图: lx_url/views.py from django.http import HttpResponse from django.shortcuts import render # Create your views here. def operation(request, num1, operator, num2): ''' 视图函数 :param request: 视图函数必需参数 :param num1: urls.py 中传入的参数, 用来计算的正整数 :param operator: urls.py 中传入的参数, 用来计算的运算符, add: 加法, sub: 减法, mul: 乘法 :param num2: urls.py 中传入的参数, 用来计算的正整数 :return: ''' if operator == 'add': cal_operator = '+' elif operator == 'sub': cal_operator = '-' elif operator == 'mul': cal_operator = '*' else: return HttpResponse(f'运算符错误! 选择的运算符: {operator}不是add、sub、mul') result = eval(f"{num1} {cal_operator} {num2}") return HttpResponse(f'{num1} {cal_operator} {num2} = {result}') def re_operation(request, num1, op, num2): ''' 视图函数 :param request: 视图函数必需参数 :param num1: urls.py 中传入的参数, 用来计算的正整数 :param op: urls.py 中传入的参数, 用来计算的运算符, add: 加法, sub: 减法, mul: 乘法 :param num2: urls.py 中传入的参数, 用来计算的正整数 :return: ''' if op == 'add': cal_operator = '+' elif op == 'sub': cal_operator = '-' elif op == 'mul': cal_operator = '*' else: return HttpResponse(f're_path 运算符错误! 选择的运算符: {op}不是add、sub、mul') result = eval(f"{num1} {cal_operator} {num2}") return HttpResponse(f're_path: {num1} {cal_operator} {num2} = {result}')
- re_path: 使用正则表达式匹配url
URL的反向解析
-
URL的绝对地址和相对地址
- 绝对地址: http://127.0.0.1/8000/index, ip + port + 地址
- 相对地址:
- 带斜杠的相对地址: 不论是在哪个地址请求的,请求后都会变成这个 http://ip:port/url
- 如: /page, 拼接为: http://ip:port/page, 不论是在哪个地址请求的,请求后都会变成拼接后url
- 不带斜杠的相对地址: 在当前访问的URL后, 将设置的相对地址拼接到后面
- 如: page, 如果是在http://127.0.0.1/8000/index这个地址中请求的, 请求后url为: http://127.0.0.1/8000/index/page
- 带斜杠的相对地址: 不论是在哪个地址请求的,请求后都会变成这个 http://ip:port/url
-
URL反向解析
-
URL反向解析是指在视图或模板中,用 path 定义的名称来动态查找或计算出响应的路由
-
path 函数语法:
- path(route, views, name='别名')
- path('page', views.page_view, name='page_url')
-
根据 path 中 name 关键字传参给URL确定了一个唯一确定的名字, 在模板或视图中, 可以通过这个名字反向推断出此URL信息
-
在模板中 - 通过url标签实现地址的反向解析
- 不带参数的URL: {% url '别名' %}
- 带参数的URL: 不论是字符串还是数字, 在模板中都要使用字符串的方式
- 位置传参: {% url '别名' '位置参数1' '位置参数2' %}
- 关键字传参: {% url '别名' name='xx' age='10' %}
# app 中的 urls.py from django.urls import path, re_path from . import views urlpatterns = [ path('test_url', views.test_url, name='tr'), path('base_index', views.base_view, name='base_index'), ] # app 中的 views.py from django.template import loader from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render def test_url(request): return render(request, 'test_url.html') def base_view(request): return render(request, 'base.html') # app 中的templates/test_url.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>EST URL</title> </head> <body> <a href="{% url 'base_index' %}">这是反向解析的url</a> </body> </html>
- 在视图函数中, 可以调用Django中的 reverse 方法进行反向解析
- 语法:
- from django.urls import reverse
- reverse('别名', args=[], kwargs=[])
- 语法:
# app 中的 urls.py from django.urls import path, re_path from . import views urlpatterns = [ path('test_url_redirect', views.test_url_redirect, name='trd'), path('test_url', views.test_url, name='tr'), ] # app 中的 views.py from django.urls import reverse from django.template import loader from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render def test_url_redirect(request): '''重定向反向解析''' reverse_url = reverse('tr') return HttpResponseRedirect(reverse_url)
-
- 练习1:
- 浏览器访问网址:http://127.0.0.1:8000/page/1,页面显示:这是编号为1的网页
- 浏览器访问网址:http://127.0.0.1:8000/page/2,页面显示:这是编号为2的网页
- 傻瓜式实现
# lx_url app路由:lx_url/urls.py 文件 from django.urls import path, re_path from . import views urlpatterns = [ path('page/1', views.page1_view), path('page/2', views.page2_view), ] # lx_url app视图:lx_url/views.py from django.http import HttpResponse from django.shortcuts import render # Create your views here. def page1_view(request): return HttpResponse('这是编号为1的网页') def page2_view(request): return HttpResponse('这是编号为2的网页')
- 以上虽然可以实现,但是如果有100个网页,需要复制100遍;优化代码,使用变量参数的方式实现
# lx_url app路由:lx_url/urls.py 文件 from django.urls import path, re_path from . import views urlpatterns = [ # <int:page>: <参数数据类型:参数变量名> path('page/<int:pg>', views.page_view), ] # lx_url app视图:lx_url/views.py from django.http import HttpResponse from django.shortcuts import render # Create your views here. def page_view(request, pg): ''' 视图函数 :param request: 视图函数必需参数 :param pg: urls.py 中传入的参数 :return: ''' return HttpResponse(f'这是编号为{pg}的网页')
- 练习2:
- 浏览器输入: http://127.0.0.1:8000/operation/{num1}/{operator}/{num2}, 页面展示 num1 * num2 = num1和num2计算结果,num1和num2是正整数,operator是add(加法), sub(减法), mul(乘法)
# app路由配置 lx_url/urls.py from django.urls import path, re_path from . import views urlpatterns = [ # <int:page>: <参数数据类型:参数变量名> path('operation/<int:num1>/<str:operator>/<int:num2>', views.operation), ] # app视图 lx_url/views.py from django.http import HttpResponse from django.shortcuts import render # Create your views here. def operation(request, num1, operator, num2): ''' 视图函数 :param request: 视图函数必需参数 :param num1: urls.py 中传入的参数, 用来计算的正整数 :param operator: urls.py 中传入的参数, 用来计算的运算符, add: 加法, sub: 减法, mul: 乘法 :param num2: urls.py 中传入的参数, 用来计算的正整数 :return: ''' if operator == 'add': cal_operator = '+' elif operator == 'sub': cal_operator = '-' elif operator == 'mul': cal_operator = '*' else: return HttpResponse(f'运算符错误! 选择的运算符: {operator}不是add、sub、mul') result = eval(f"{num1} {cal_operator} {num2}") return HttpResponse(f'{num1} {cal_operator} {num2} = {result}')
- re_path 练习3:
- 访问地址: http://127.0.0.1:8000/birthday/四位数字/一到两位数字/一到两位数字
- 访问地址: http://127.0.0.1:8000/birthday/一到两位数字/一到两位数字/四位数字
- 最终输出: 生日为: xxxx年xx月xx日
# app的路由: lx_url/urls.py from django.urls import path, re_path from . import views urlpatterns = [ re_path(r'birthday/(?P<num1>[0-9]{4})/(?P<num2>[0-9]{1,2})/(?P<num3>[0-9]{1,2})$', views.re_librthday), re_path(r'birthday/(?P<num1>[0-9]{1,2})/(?P<num2>[0-9]{1,2})/(?P<num3>[0-9]{4})$', views.re_librthday), ] # app的视图: lx_url/views.py from django.http import HttpResponse from django.shortcuts import render def re_librthday(request, year, month, day): year = int(year) month = int(month) day = int(day) if month > 0 and month < 13: if month in (1, 3, 5, 7, 8, 10, 12) and day > 0 and day < 32: result = f'生日为: {year}年{month}月{day}日' elif month in (4, 6, 9, 11) and day > 0 and day < 31: result = f'生日为: {year}年{month}月{day}日' elif month == 2 and day > 0 and day < 30: result = f'生日为: {year}年{month}月{day}日' else: result = f'day 错误! year: {month}, month: {year}, day: {day}' else: result = f'month 错误, month 不是1到12之间的正整数! month: {year}' return HttpResponse(result)