9.零基础快速入门Python Web开发——路由系统扩展

URL参数传递

path()函数、re_path()函数允许向视图传递额外参数,这些参数存放在一个字典类型的数据中,该数据的键代表参数名,值代表参数值。re_path()函数与path()函数传递额外参数方式相同,以path()函数为例介绍如何向视图传递额外参数。

2.3.1 传递URL中获取的数据

使用path()函数解析URL时,可以在URL模式中使用“<变量名>”来捕获URL路径中的数据,示例代码如下。

path('test/<urldata>',views.getdata),

Django在解析URL时,会将路径“/test/xxx/”的“xxx”作为值传递给变量urldata。同时还需要再视图函数getdata()中定义一个名为urldata的参数。

下面的实例在项目视图文件testurl\testurl\views.py中添加一个视图函数,将URL中获取的数据输出到响应页面。

具体步骤如下。

  1. 在“testurl\testurl\views.py”中添加一个视图函数.
def getdata(request,data2):

    return HttpResponse('这里的路径是:%s' %(data2))
  1. 打开“testurl\testurl\urls.py”文件,添加访问视图函数getdata的URL配置,代码如下。
....

from . import views

urlpatterns = [

....

path('test/<data2>',views.getdata),

]
  1. 在浏览器中访问“http://127.0.0.1:8000/test/ilovedjango”,结果如图2-7所示。

图 2-7 获取URL中的数据输出到页面

本例中的URL路径“/test/ilovedjango”与URL模式“test/<data2>”匹配,“ilovedjango”作为数据传递给视图函数的参数data2。

2.3.2 路径转换器

内置路由转换器可以显式地指定路由中参数的数据类型,Django中内置了5种路由转换器,分别为str、int 、slug 、uuid 和path 。

  1. str:匹配任何非空字符串,但不包含路由分隔符“/”。如果URL中没有指定参数类型,默认使用该类型。
  2. int:匹配0或任何正整数。
  3. slug:匹配由字母、数字、连字符和下画线组成的URL。
  4. uuid:匹配一个uuid。为了防止多个URL映射到同一页面中,该转换器必须包含连字符,且所有字母均为小写。
  5. path:匹配任何非空字符串,包括路由分隔符“/”。

下面的例子在项目视图文件“testurl\testurl\views.py”中添加定义两个视图函数,使用常用的str和int路径转换器。

具体步骤如下。

  1. 在项目视图文件“testurl\testurl\views.py”中添加如下代码。
def index_world(reqeust,world):

    return HttpResponse(world)    #定义路由转换器为str路由转换器



def index_num(request,number):

    return HttpResponse('这里的路径是:%s' %(number))   #定义路由转换器为int路由转换器
  1. 打开“testurl\testurl\urls.py”文件,添加访问视图函数index_world和index_num的URL配置,代码如下。
....

from . import views

urlpatterns = [

....

    path('world/<str:world>',views.index_world), #str路由转换器

    path('num/<int:number>',views.index_num),   #int路由转换器

]
  1. 在浏览器中访问“http://127.0.0.1:8000/world/abc123”,结果如图2-8所示。

图 2-8 获取URL中的字符串

  1. 因为使用了str转换器,匹配任何非空字符串,当输入127.0.0.1:8000/world/abc123时,能够成功响应,当输入127.0.0.1:8000/num/abc123,结果如图2-9所示。因为int路径转换器 只是匹配0或任何正整数。而传递的参数abc123显然不符合。

图 2-9 获取URL中数字失败

  1. 在浏览器中访问“http://127.0.0.1:8000/num/123”,结果如图2-10所示。这里传递的参数123符合int转换器类型。

图 2-10 获取URL中数字成功

2.3.3 传递附加参数

使用path()或re_path()的第三个参数可以向视图传递额外参数。例如在“testurl\testurl\urls.py”文件中定义如下URL模式。

path('<data>',views.getextrdata,  {'ex':'python web'}),

路由系统匹配到以上URL模式时,会调用views.getextrdata函数,并向该函数传递值为‘python web’的参数ex。

URL模式中向视图传递了参数,那么视图必然定义了接收该参数的形参。在“testurl\testurl\urls.py”视图中,添加如下视图。

def getextrdara(request,data,ex):

    return HttpResponse('从URL获取的参数是:%s,附加数据为:%s '%(data,ex))

此使访问“http://127.0.0.1:8000/hello”,结果如图2-11所示。“hello”为从URL获取的参数,“python web”为视图将参数书ex的值签到在响应信息返回的数据。

图 2-11 传递URL中获取的数据与附加参数

2.4 反向解析

使用Django开发应用时可以直接使用URL,但此种方式URL与项目耦合度较高,如果urls.py中修改了某个页面的URL,那么视图或模板都需要修改,在维护或更新项目过程中都有可能出现错误。Django使用urls模块中的reverse()函数实现反向解析。

反向解析URL可以通过URL模式的名称或视图函数名称来获得访问视图函数的URL。reverse()函数的语法格式如下。

reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)

  1. viewname:必选参数,URL模式名称或可调用的视图对象。
  2. urlconf:可选参数,一个包含URL模式的URLconf模块。
  3. args:可选参数,传递给URL的列表类型的参数。
  4. kwargs:可选参数,传递给URL的字典类型的参数。
  5. current_app:可选参数,当前视图所属的应用。

2.4.1 反向解析命名URL模式

可用reverse(“URL模式名称”)语句来获得URL。

下面的例子在第一单元创建的项目视图文件“helloworld\helloworld\views.py”添加视图函数geturl。

  1. 修改“helloworld\helloworld\views.py”,添加定义视图函数,其中“two”为hello视图函数的路由命名。
from django.http import HttpResponse

from django.urls import reverse

def hello(request):

return HttpResponse("Hello world  ")



def geturl(request):

    return HttpResponse('反向解析的url地址是: %s' %reverse('two'))
  1. 在项目URL配置文件“helloworld\helloworld\urls.py”中添加URL映射,并且为Path(‘', views.hello)路径添加命名。
from django.conf.urls import url

from . import views

urlpatterns = [

Path(‘helloworld', views.hello,name='two'),

 path('rev/ccit123',views.geturl,name='one'),

 ]
  1. 在浏览器中访问http://127.0.0.1:8000/rev/ccit123,页面的输出结果如图2-12所示。

图 2-12 反向解析命名URL模式

2.4.2 反向解析视图函数

可以使用视图函数名称作为reverse()函数参数来执行反向解析,这与反向解析命名URL模式类似。

下面的例子在第一单元创建的项目视图文件“helloworld\helloworld\views.py”修改视图函数geturl。

  1. 修改“helloworld\helloworld\views.py”,将geturl中reverse ('URL模式名称'))更改为reverse(geturl)),geturl为视图名称。在页面中输出浏览器请求的URL路径会返回geturl配置的路由路径。
def geturl(request):

    # return HttpResponse('反向解析的url地址是: %s' %reverse('two'))  方法一

    return HttpResponse('反向解析的url地址是: %s' % reverse(geturl))
  1. 在项目URL配置文件“helloworld\helloworld\urls.py”不需要更改,在浏览器中访问http://127.0.0.1:8000/rev/ccit123,页面中的输出结果如图2-13所示。

图 2-13 用视图函数名作为参数反向解析URL

2.4.3 在模板中反向解析URL

在模板中也可以用反向解析来获得访问视图函数的URL,基本格式如下。

    {% url URL模式名称 参数 %}

下面的例子在项目视图文件“helloworld\helloworld\views.py”添加视图函数,在模板中使用反向解析函数获得访问视图函数的URL。

具体步骤如下。

  1. 在“helloworld\helloworld\”文件夹下新建templates文件,并在其中创建helloworld.html文件,添加下面的代码定义模板。
{% url URL模式名称 参数 %}

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Title</title>

</head>

<body>

        <h1>你好</h1>

        {% url 'two'%}

        <div>

            <p><a href="{% url 'two'%}">点击我</a> </p>

        </div>

          <div>

            <p><a href="{% url 'two'%}">点击我</a> </p>

        </div>

          <div>

            <p><a href="{% url 'two'%}">点击我</a> </p>

        </div>

          <div>

            <p><a href="{% url 'two'%}">点击我</a> </p>

        </div>

<hr>

</body>

</html>
  1. 修改“helloworld\helloworld\views.py”,添加下面的代码定义视图函数。
def index2(request,):

    return  render(request,'helloworld.html')
  1. 为index2视图函数配置路由,代码如下。
path('second/',views.index2),
  1. 在浏览器中访问http://127.0.0.1:8000/second/,页面输出结果如图2-14所示。可以发现 HTML中定义的{% url 'two'%}变量在页面中显示为index函数的路由路径。

图 2-14 在模板中反向解析URL

  1. 在helloworld.html文件中,将变量放在了超链接中,点击其中一条连接,页面调转到了helloworld项目页面,如图2-15所示。

图 2-15 hellowold页面

由此可以实例可以发现,在实际开发中,当前端页面出现较多相同链接。可以使用在模板中反向解析URL的方式定义各个链接,后期需要更改URL地址时,开发人员不需要更改前端超链接网址,只需要在路由配置时更改route即可。例如,将helloworld/路径更改为hw/,只需要在urls.py中修改index函数的路由配置路径。

 #path('helloworld/',views.index,name='one'),

 path('hw/',views.index,name='one'),
  1. 再次在浏览器中访问http://127.0.0.1:8000/second/,页面输出结果如图2-16所示。

图 2-16 在模板中反向解析URL

2.5 URL命名空间

url的命名空间往往是和反向解析模式结合使用的,当涉及到多个应用分配路由,且函数或URL名可能出现重名的情况,我们需要给它们设置命名空间来帮助 reveser函数来避免混淆。正确使用URL命名空间,可对项目中的应用进行多次部署,级可通过不同的URL访问同一个应用。

Django将URL命名空间分为应用命名空间和实例命名空间。

2.5.1 应用命名空间

应用命名空间指正在部署的应用的URL命名空间名称。一个应用的多个实例可共享同一个应用命名空间,也可配置多个应用命名空间。下面通过一个实例来讲解应用命名空间的功能和配置方式。

实例:在项目文件app02下创建两个应用app03和app04,分别为他们配置路由表,路径名一样,命名也一样。如图2-17和2-18所示

图 2-17 app03应用路由表

图 2-18 app04应用路由表

在根路由表app02\app02\urls.py下使用include()函数进行路由分发。如图2-19所示。应用app03的路径应为app03/login,应用app04的路径应为app04/login

图 2-19 根路由路径设置

分别在app03和04应用中中创建视图函数login:业务逻辑完全相同,通过视图函数名来逆向解析出路由路径。如图2-20所示。

图 2-20 app03与app04视图定义

启动开发服务器,输入app03/login查看反向解析的数据,正常情况下逆向解析返回的数据应该是app03/login,实际显示结果如图2-21所示。逆向解析数据错误。

图 2-21 通过视图函数名反向解析app03路径

分析出错原因,不难发现,就是文件开头提到的,当涉及到多个应用分配路由,且函数或URL名可能出现重名的情况, reveser函数出现了混淆。因此我们需要给它们设置命名空间来帮助 reveser函数来避免混淆。应用命名空间使用方式如下。分别在app03\urls.py和app04\urls.py中输入app_name=‘应用命名空间名’来设置应用命名空间名。

 2-22 app03应用名设置

图 2-23 app04应用名设置

修改应用app03与app04视图函数,在反向解析reverse中输入“应用名:视图函数名”的形式。

 2-24 app03视图函数设置

图 2-25 app04视图函数设置

应用命名空间配置完成后登录开发服务器在url中输入http://127.0.0.1:8000/app04/login和http://127.0.0.1:8000/app03/login查看反向解析是否成功。

 2-26 app03视图函数设置

图 2-27 app04视图函数设置

比较2-26和2-27可知,通过设置应用命名空间可以正确区分不同应用中同名的URL。

2.5.2 实例命名空间

实例命名空间是应用特定实例的URL命名空间。实例命名空间名称在整个项目中必须唯一。Django中允许多个应用的URL指向同一个应用的URLconf,在视图中使用应用命名空间实现反向解析时出现URL匹配混淆,例如项目chapter02的根URLconf中定义了URL模式。

 path('path-one/',include(‘app04.urls’)),

 path('path-two/',include(‘app04.urls’)),

该项目app04应用的urls.py定义了URL模式,具体如下。

 path('index/',include(‘app04.urls’,views.url_path,name=’url_path’),

该项目app04应用的views.py定义了url_path()视图,具体如下。

def url_path(request):

Return HttpResponse(f”当前url为:{reverse(‘app04:url_path’)}”)

此时,访问/path-one/index/或/path-two/index/,页面中均响应“当前url为:/path-one/index/”,这是因为反向解析URL都满足根URLconf中第一条URL规则。页面响应结果如图2-28所示。

图 2-28 响应结果

但期望视图函数能根据URL的具体路径响应不同的信息。为解决这个问题,可以设置URL实例命名空间。实例命名空间在include()函数中设置参数namespace的值,其格式如下。

 path('index/',include('app04.urls',namespace='app04')),

在chapter02项目的根URLconf中为URL设置实例命名空间,具体如下。

urlpatterns = [

    path('path-one/',include('app04.urls',namespace=’one’)),

    path('path-two/',include('app04.urls',namespace=’two’)),

]

修改app04应用url_path()视图,在该视图中通过request.resolver_match.namespace获取当前URL实例的命名空间,区分当前调用URL的应用,使反向解析能获得正确的结果。实例如下。

def url_path(request):

return HttpResponse(f”当前url为:{(reverse(‘app04:url_path’,current_app=request.

resolver_match.namespace))}”)

此使,访问/path-one/index/页面响应“当前url为:/path-one/index/”;访问/path-two/index/页面响应“当前url为:/path-two/index/”。设置实例命名空间响应结果。如图2-29所示。

图 2-29 响应结果

2.6本章小结

本章介绍了Django框架中的路由系统,包括如何处理Http请求。路由转换器、如何利用正则表达式配置URL、通过include()函数实现路由分发、向视图传递额外参数、URL命名与命名空间、反向解析URL。Django的URL分发机制将用户访问的URL与实现输出页面的视图函数、模板、模型等隔离,也在一定程度上保障了站点安全。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值