fengyu-9191

参考博客: https://www.cnblogs.com/yuanchenqi/articles/8876685.html

Django路由

1.简单的路由配置

from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app01 import views

urlpatterns = [
    # 根据客户端请求的路径,分配路由。
    # path()是完全匹配,re_path()是使用正则匹配
    # path("login/")相当于re_path(r"^login/$")  路径指定以l开头,以/结尾

    re_path(r\'^articles/2003/$\', views.special_case_2003),
    path("articles/2003/",views.special_case_2003),
]

注意:

  •     若要从URL 中捕获一个值,使用re_path(),需要在正则里的周围放置一对圆括号(分组)。
  •     不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles
  •     每个正则表达式前面的\'r\' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
  •  正则里最好使用 ^ 和 $ 来约束开头和结尾

 

2.  re_path( )里的正则,使用无名分组,获取url中需要的参数

  使用re_path() 正则里的分组,来获取GET请求中,url路径中需要的部分参数,便于在视图(views.py的函数)里使用。

  注意: 无名分组,一个正则中匹配的多个分组项,是按位置和视图函数一一对应的

   urls.py内容如下:

from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app01 import views

urlpatterns = [
    # 根据客户端请求的路径,分配路由。
    # path()是完全匹配,re_path()是使用正则匹配
    # path("login/")相当于re_path(r"^login/$")  路径指定以l开头,以/结尾

    # 【重要】 re_path里的正则表达式里,如有()进行了分组,则匹配成功后,会将匹配的分组内容,当作参数,调用views.py里对应的函数
    re_path(r"^articles/2003/$", views.special_year),  # special_year(request)
    re_path(r"^articles/(\d{4})/$", views.year_archive),  # year_archive(request,\'2020\')
    re_path(r"^articles/(\d{4})/(\d{2})/$", views.year_month_archive),  # year_archive(request,\'2020\',\'01\')
    # 【注意】路由很多时,一定要注意上下匹配先后问题,程序从上往下执行,一旦匹配成功,马上执行,后面的即使能匹配,也不执行了。

    # 浏览器输入: https://127.0.0.1:8000/articles/2003/ 调用views.py里的 special_year(request),而不是调用 year_archive(request,\'2003\'),因为只执行一次匹配
    # 浏览器输入: https://127.0.0.1:8000/articles/2020 调用views.py里的 year_archive(request,\'2020\')
    # 浏览器输入: https://127.0.0.1:8000/articles/2020/01 调用views.py里的 year_month_archive(request,\'2020\',\'01\')
]

  views.py内容如下:

from django.shortcuts import render,HttpResponse
#render是一个函数,HttpResponse是一个类

# Create your views here.
import time,datetime

def special_year(request):  
    # 去数据库查询所有2003年的文章
    return HttpResponse("special_year:2003 OK")

def year_archive(request,year):  #这里的year拿到的是 字符串类型
    # 去数据库查询所有指定年份的文章
    return HttpResponse(year)

def year_month_archive(request,year,month):
    # 去数据库查询指定年、指定月份的文章
    return HttpResponse("year:%s month:%s" %(year,month))

  使用浏览器访问:

  ----- ----

 

3.有名分组 (对比上面的无名分组)

  • 正则里使用 ( ) 进行分组
  •  使用 ?P< 关键字> 来给该分组起名字

urls.py如下:

from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app01 import views

urlpatterns = [
    # 根据客户端请求的路径,分配路由。
    # path()是完全匹配,re_path()是使用正则匹配
    # path("login/")相当于re_path(r"^login/$")  路径指定以l开头,以/结尾

    # 无名分组
    # re_path(r"^articles/(\d{4})/(\d{2})/$", views.year_month_archive),  # year_archive(request,2020,01)
    
    # 有名分组  ()用来分组; ?P<**>用来给该分组起个名字(关键字)
    re_path(r"^articles/(?P<year>\d{4})/(?P<month>\d{2})/$", views.year_month_archive2), # year_archive2(request,year=\'2020\',month=\'01\')
]

 

views.py如下:

from django.shortcuts import render,HttpResponse
#render是一个函数,HttpResponse是一个类

def special_year(request):
    # 去数据库查询所有2003年的文章
    return HttpResponse("special_year:2003 OK")

def year_archive(request,year):
    # 去数据库查询所有指定年份的文章
    return HttpResponse(year)

def year_month_archive(request,year,month): # 无名分组时,year 和 month 的前后位置关系,必须和路由里的正则匹配时一样。 另外,无名分组的函数里,参数名可以随便起,例如 year_month_archive(request,y,m)也是可以的。
    # 去数据库查询指定年、指定月份的文章
    return HttpResponse("year:%s month:%s" %(year,month))

def year_month_archive2(request,month,year): # 有名分组时,year和month参数,顺序就可以打乱写了。 有名分组里的函数的参数名,必须和正则里的分组名一样,否则函数调用时会报错。
    # 去数据库查询指定年、指定月份的文章
    return HttpResponse("year:%s month:%s" %(year,month))

 

 4.路由分发 (适合较大项目,项目下有多个应用)

  当项目较大时,再使用全局的urls.py来分发到多个不同应用的视图函数,会降低阅读、维护的难度。

  所以,可以通过全局urls.py首先根据应用,进行首次路由分发到各个应用的urls.py。到达应用层后,再由各个应用的urls.py进行分发到视图函数。

4.1 全局 url.py

#全局 urls.py
from django.urls import path, re_path, include

# django 2.往后的版本,要使用正则,需要引入re_path

# 如果项目较大,有多个应用,则在全局的路由里,需要进行一次路由分发,即发送到各个应用的路由。需要引入include()函数

urlpatterns = [
    # 根据客户端请求的路径,首先分配到各个应用的路由。

    # 此示例中,整个项目首页,也分发在一个应用里,该应用只用来显示主页
    re_path("^$",include("app_index.urls")),  # 以空开头,以空结尾,匹配根目录。一般用来显示主页等。

    # 根据项目里的应用,进行路由分发
    re_path(\'app01/\', include(\'app01.urls\')),  # 从url从匹配到 "app01"后,将后面的路径,分发到 app01.url.py的路由里
    re_path(\'app02/\', include(\'app02.urls\')),  # 从url从匹配到 "app02"后,将后面的路径,分发到 app02.url.py的路由里
]
全局 urls.py

 

4.2 各应用的 urls.py (需要自己创建该.py文件。可以直接复制全局的代码过来,稍作修改)

  app01的urls.py:

 

   app02的urls.py:

 

   app_index的 urls.py:

# app01的urls.py
from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app01 import views

urlpatterns = [
    re_path("^$", views.index),  # 分发到 应用app01的首页

    re_path(r"^articles/2003/$", views.special_year),  # special_year(request)
    re_path(r"^articles/(\d{4})/$", views.year_archive),  # year_archive(request,\'2020\')

    # 有名分组  ()用来分组; ?P<**>用来给该分组起个名字(关键字)
    re_path(r"^articles/(?P<year>\d{4})/(?P<month>\d{2})/$", views.year_month_archive2),  # year_archive2(request,year=\'2020\',month=\'01\')
]
# app01的urls.py
# app02的 urls.py
from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app02 import views

urlpatterns = [
    re_path("^$",views.index),  # 分发到 应用app02的首页
    re_path("^timer/$",views.timer),
]
# app02的urls.py
# app_index 的 urls.py
from django.contrib import admin
from django.urls import path, re_path
# django 2.往后的版本,要使用正则,需要引入re_path

# 必须导入自己创建的应用里的views视图.py文件
from app_index import views

urlpatterns = [
    re_path("^$", views.index),  #发到 应用app_index的首页,此示例,把此应用的首页,作为整个项目的首页
]
# app_index的 urls.py

 

4.3 各应用的 views.py

 

4.4 使用浏览器访问:

====

 ==

# app_index的views.py
from django.shortcuts import render,HttpResponse
#render是一个函数,HttpResponse是一个类

# Create your views here.

# 函数1 主页
def index(request):
    return HttpResponse("项目 主页")
# app_index的views.py
# app01 的views.py
from django.shortcuts import render,HttpResponse
#render是一个函数,HttpResponse是一个类

# Create your views here.
import time,datetime

def special_year(request):
    # 去数据库查询所有2003年的文章
    return HttpResponse("special_year:2003 OK")

def year_archive(request,year):
    # 去数据库查询所有指定年份的文章
    return HttpResponse(year)

def year_month_archive(request,year,month): # 无名分组时,year 和 month 的前后位置关系,必须和路由里的正则匹配时一样
    # 去数据库查询指定年、指定月份的文章
    return HttpResponse("year:%s month:%s" %(year,month))

def year_month_archive2(request,month,year): #有名分组时,year和month参数,顺序就可以打乱写了。
    # 去数据库查询指定年、指定月份的文章
    return HttpResponse("year:%s month:%s" %(year,month))
# app01 的views.py
# app02 的views.py
from django.shortcuts import render,HttpResponse
#render是一个函数,HttpResponse是一个类

# Create your views here.
import time,datetime

# 函数1 主页
def index(request):
    return HttpResponse("app02 主页")

# 函数2 显示当前时间给前端
def timer(request):
    now=str(datetime.datetime.now())
    return HttpResponse("app02 当前时间: "+now)
# app02 的views.py

 

 5. 反向解析 (可以理解为在路由分发时,使用 别名) ---- 别名在html文档里的应用

1.url路由里,设置 别名

 

 2.视图函数里,执行render(request,\'login.html\')时,django将检索特殊语法,将html里的特殊语法进行替换

 

 3.html文件 表单提交时的 url使用 {% url \'别名\' %},来替代直接写死的方式

 

 4.当对外的接口发生变化时,需要修改的代码量就很少。使用浏览器访问如下:

 ------

 

6.反向解析 (可以理解为在路由分发时,使用 别名) ---- 别名在html文档里的应用2 (路由里包含分组的动态参数时)

  在上面的正则中,没有分组的动态参数。当正则中含有分组的动态参数时,html里使用别名时,就必须配上对应的参数

 

 7.反向解析 的另一应用场景 -----  别名在views.py视图函数里的应用1

 1.在urls.py里设置路径别名

   

 

 2. 在views.py里,导入 reverse方法

from django.urls import reverse

  

 

 8.反向解析 的另一应用场景 -----  别名在views.py视图函数里的应用2

  上面第7点,正则中没有分组的动态参数。

  现在,如果正则里有分组的动态参数,则在views.py中,使用 reverse()时,必须传入 args=(参数1,参数2...)

  

 

总结:

  路径使用别名的好处: 假如我们的视图函数、或者html模板中有用到路径,如果把路径写死成固定字符串,一旦后期对外接口发生变化,我们用到此路径的地方,也必须手动同步修改,维护难。使用别名,则很好的解决了这种问题。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

--

 

 

--------

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-06-07
  • 2022-01-22
  • 2022-01-26
  • 2022-12-23
  • 2022-12-23
  • 2021-08-10
猜你喜欢
  • 2022-01-18
  • 2022-02-26
  • 2021-12-24
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案