【4】Django----URL路由配置

一、URL路由配置的用途

  URLDjango收到用户请求后,根据用户请求的URL地址和urls.py里配置的映射关系,以正确的确定出某个URL调用哪一段逻辑代码来对应执行相应的视图函数或视图类,最后由视图返回给客户端想要接收的数据。

  简单的例子:

from django.urls import path

urlpatterns = [
    path('index', views.index),
]
# index这个路由对应着视图函数中index这个方法,浏览器输入这个链接,就会响应到index这个函数来执行

二、URL配置的位置与方法

2.1 URL配置的位置

  • 项目目录中的urls.py,通常情况下当应用仅有一个的时候只在此位置配置即可
  • 应用目录中的urls.py,当应用大于2个时,会导致项目目录下urls.py中配置过多,且难以区分是哪个应用对应的URL,这时需要在项目目录urls.py中配置进行路由分发,各应用下创建一个名为urls.py文件,然后配置各应用下的URL,以将不同应用的URL配置隔离开来

2.2 URL配置的方法

  • Django1.x版本中(现在几乎不用)
from django.conf.urls import url
from app_name import views
urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
      url(r'^blog/$', views.blog), # 例子
]
  • Django2.x和3.x版本中(path为主)
# re_path就是一个具有正则表达式功能的路径
from django.urls import path,re_path,include
from app_name import views
from django.contrib import admin
urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r"^articles/2003/$",views.special_case_2003), # 正则,只能是字符串
    path("articles/<int:month>",views.month), # path转换器,可以转换格式
    path("app01",include(app01.urls))
]

三、settings.py中的URL配置

  • APPEND_SLASH: Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但Django中默认这个参数为True, 其作用就是自动在网址结尾加/,由django.middleware.common.CommonMiddleware这个中间件来实现的
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True

四、URL路由配置之有名分组(re_path)

  Python函数传参时一般是通过位置传参,这种方式可能会导致我们在编写视图中出现一些错误,因此需要使用Python的关键字传参的方法来对其进行传参,这样就不会因为参数的位置而导致错误的发生。这种URL配置好处就是没有位置紊乱的问题,但是需要注意的是,视图里面只能是<name>里面的name,不能换为其它名称。

# re_path就是一个具有正则表达式功能的路径
from django.urls import path,re_path
from app01 import views
urlpatterns = [
	# 此方式只能是year_month(request,y=year,m=month),才能保证正确传参
    re_path(r"^articles/([0-9]{4})/([0-9]{2})/$",views.year_month),
    # year_month(request,y=year,m=month)或者year_month(request,m=month,y=year)都可以
    re_path(r"^articles/(?p<year>[0-9]{4})/(?p<month>[0-9]{2})/$",views.year_month),
]

五、URL路由配置之path转换器

5.1 path内置转换器介绍

rlpatterns = [ 
    re_path("^articls/(?p<articls_id>[0-9]{4})/detail$",views.detail)
    re_path("^articls/(?p<articls_id>[0-9]{4})/edit$",views.edit)
    re_path("^articls/(?p<articls_id>[0-9]{4})/delete$",views.delete)
]

问题的提出:

  • 前面re_path所传输的其实都是字符串,字符类型能否自动转换以便于我们使用呢
  • 以上urlpatterns中后三个url中有相同的正则,是否能够只修改一处正则即可实现不同的url,而避免因正则发生变化而做重复性的工作呢

path使用的基本规则

  • 使用<>url中捕获值,无需在前面添加前导斜杠/
  • 捕获值可以包含一个转化器类型convert type,如<int:name>捕获到整数变量,也属于有名分组
  • 如果不使用转换器,将会匹配到任何字符串,也包括/
转换器类型类型说明
<int:number>number转换为整型,匹配0或任何正整数
<str:name>name转换为浮点型,匹配除了/之外的非空字符
<slug:path1>匹配字母、数字、下划线组成的字符串
<uuid:path2>匹配格式化的UUID唯一识别码
<path:path3>匹配任何非空字符,包括路径分割符,除外

5.2 自定义path内置转换器

  • 和前面应用中urls.py类似,新建一个py文件来保存
# 比如新建一个urlconvert.py于app01中
class MonthConvert:
    # 需要设定的正则表达式
    regex = "[0-9]{2}" # 这是一个属性命名,这里不能更改,只能是这样
    
    def to_python(self,value):
        """用于url设定的内置转换器"""
        return int(value)
    
    def to_url(self,value):
        """用于url反向解析"""
        return '%04d' % value
  • 然后通过register_converter进行注册
from django.urls import register_convert
# 将之前所写的类也加进来
from app01.urlconvert import MonthConvert

register_convert(MonthConvert,"mm") # "mm"是一个标记

5.3 path转换器的使用

urlpatterns = [
    re_path("articles/(?p<m>[0-9]{2})",views.month)
    path("articles/<int:month>",views.month),
    path("articles/<mm:month>",views.month),
]
  • 以上三种方式对应的路径是相同的,不同之处在于后两个返回的都是int,前面是str
  • 可通过int(m)将其转换一下,此时则相同了

六、URL控制之反向解析

  • 其目的就是防止路径写死,使URL的使用变得更加灵活,从而不利于开发者维护
  • 通过在urls.py配置URL时添加一个别名name=“val”,注意val保证唯一性,然后可以利用name值来进行反向解析出配置的URL

6.1 模板中URL的反向解析

  • 创建一个login.html
  • 创建一个login视图
    • 通过getpost来进行判断与验证
    • get请求用于显示login.htmlpost请求用于验证,跳转至其它页面,在Django中通过request.method来查看请求方法
# django项目中的settings.py需要注释掉这一行,这是一个跨站请求的组件,
# 如果不注释掉会报一些错误,也可以通过在模板中加入csrf-token的模板标签和视图中加入装饰器避免错误
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# file:login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>

<form action="{% url "Log" %}" method="post">
    用户名:<input type="text" name="user">
    密码:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>
  • {% naeme %}是专用于渲染html标签的,{% url "name" %}专用于URL的反向解析,在具体的URL配置中添加name来实现,如下面代码所示,通过另起一个名为Log来作为匹配的路径变量,从而将此路径放入form表单的action中。这里的name相当于前端里面的id、class的功能类似
  • 浏览器渲染此页面时,会将name所标记的url通过Django的模板语法自动渲染到模板里面
# app01的urls.py中的配置文件
# re_path就是一个具有正则表达式功能的路径
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path(r"login.html/",views.login,name="Log"),
]
# file app01/views.py
def login(request):
    # request.method用于查看是get请求还是post请求
    if request.method == "GET":
        return render(request,"login.html")
    elif:
        # request.GET获取GET请求的内容
        # request.POST获取POST请求的内容
        # 他们的结果都是一个Python字典,则可以通过get("name")来进行取值
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        if user=="qinhao" and pwd=="123456":
            return HttpResponse("登录成功")
        else:
            return HttpResponse("用户名或密码错误")
  • 此时的逻辑如下所述:
    • ① 用户首先通过输入网址,从而通过url匹配到login这个视图函数
    • ② 匹配到这个函数后,通过判断请求方式是GET还是POST请求
    • ③ 用户第一次访问是通过GET请求进去到login.html这个视图页面的,当用户输入用户名和密码后点击提交,此时即触发了一个POST请求,通过{% url "Log" %}模板语法将formactionURL自动更换为login.html/,最后提交表单又跳转至login这个视图
    • ④ 此时的请求为POST请求,然后通过验证登录名与密码,从而实现用户的登录验证

6.2 视图函数中URL的反向解析

# 从url中调用
from django.urls import reverse
	...
 	# url = reverse(name) name就是你在url所写的标签名,通过reverse即可进行url的反向解析
    url = reverse("S_C_2003")
    # 必须要满足url的正则规定,否则方向解析就会失败的出现错误,
    # 有几个正则就需要传入几个参数以元组的方式进行传输
    url = reverse("year",args=(3333,))
    ...

6.2.1 URL无正则的反向解析

# 在URL中添加name
urlpatterns = [
    path('timer/', views.timer),
    # 路由配置: 路径 ---->> 视图函数
    # ^表示必须以什么开头;$表示必须以什么结尾
    re_path(r"^articles/2003/$",views.special_case_2003,name="S_C_2003"),
    # ()表示分组有几个就表示有几个组并且需要多传入分组数的参数,
    # [0-9]表示任意的0-9,{4}表示有四个[0-9]
    re_path(r"^articles/([0-9]{4})/$",views.year,name="year"),
    path(r"login.html/",views.login,name="Log"),
]
# 从url中调用
from django.urls import reverse
from django.shortcuts import render,HttpResponse
def login(request):
    # url = reverse(name) name就是你在url所写的标签名,
    # 通过reverse即可进行url的反向解析
    url = reverse("S_C_2003")
    print(url)
    return HttpResponse("HELLO")

6.2.2 URL有正则的反向解析

# 基于上面的url,有一个正则表达式,这里就需要传入一个元组的参数才能完成这次的方向解析
# 并且必须要满足url的正则规定,否则方向解析就会失败的
from django.urls import reverse
from django.shortcuts import render,HttpResponse
def login(request):
    # url = reverse(name) name就是你在url所写的标签名,通过reverse即可进行url的反向解析
    # 有几个正则就需要传入几个参数以元组的方式进行传输
    url = reverse("year",args=(3333,))
    
    print(url)
    return HttpResponse("HELLO")

七、URL之路由分发

  • 应用于应用较多时,路由配置也就变的十分繁琐,不能有效方便的进行管理

  • 路由分发的目的就是一个应用在全局的urls.py中对应一个path

  • Django中,主路由配置文件urls.py可以不处理用户具体路由,主路由配置文件的可以做一个请求的分发(即分布式请求处理)。具体的请求可以由各应用进行处理:

7.1 在主路由中调用include函数

  • 语法:include(“appname.urls”)
  • 作用:用于将当前路由转到各个应用的路由配置文件的urlpatterns进行分布式处理。
  • 用于不同app(应用)中的name值一样时,避免name值相同而导致路径拦截或覆盖,造成所渲染的内容出错。通过在app01app02中设置urls中添加name的后面,在添加一个namespace从而区分name
# 在总项目中的urls.py中设置一个namespace
from django.urls import path,re_path,include
urlpatterns = [
    # app01是一个命名空间,include是以一个元组传输的,第一参数是
    re_path(r"^app01/",include(("app01.urls","app01"))),
    re_path(r"^app02/",include(("app02.urls","app02"))),
]

# 并在reverse函数中通过
reverse("app01:name")
# 这里的app01就是命名空间,相当于通过指定一个房子里面对应的房间号

注意:

  • 当我们使用命名空间时,无论是在哪儿,反向解析时我们都应该变为namespace:name这种格式
  • 如前面form表单里的模板就应该替换为% url "app01:Log"%}
  • namespace是不能够有重复的,一般就用app_name即可

7.1 在应用下配置urls.py

  • 在应用下手动创建urls.py文件
from django.urls import math
from . import views # 此时与views.py为同级目录
# app01应用下
urlpatterns = [
    # https://127.0.0.1:8000/app01/index
    path("index/",views.index,name="AA"),
]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

而又何羡乎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值