zoukankan      html  css  js  c++  java
  • django -- 路由

    前戏

    在之前的文章中,我们已经知道了什么是路由。路由就是urls.py文件里urlpatterns下写的一个个路径,用户输入路径之后,Django在里面找对应的路径,然后去执行views.py里的函数。前面只是学了最简单的用法,今天来看看还有哪些用法

    官方文档

    基本的格式:

    from django.conf.urls import url
    
    urlpatterns = [
         url(正则表达式, views视图,参数,别名),
    ]

    正则表达式:一个正则表达式字符串

    views视图:一个可调用对象,通常为一个视图函数

    参数:可选的要传递给视图函数的默认参数(字典形式)

    别名:一个可选的name参数

    注意

    Django2.xx的路由是下面这样的写法

    from django.urls import path,re_path
    
    urlpatterns = [
        path('login', views.login),
    
    ]

    如果你想把1.xx的升级到2.xx,要把url换成re_path

    正则表达式

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/[0-9]{2}/[0-9]{3}', views.login),
    ]

    代码解释:

    我们在路径里写了一个正则表达式,匹配两个数字/三个数字,这样就能访问到这个网站了。^表示以什么开头,如果不知道,可以去看看python的re模块

    不知道有没有发现,如果你输入两个数字一个反斜杠,后面不管输入几个数字都可以匹配到,这是因为我们没有限制以什么结尾。正则只要匹配到就不再往下查找了,我们可以在最后加个结尾符$

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/[0-9]{2}/[0-9]{3}$', views.login),
    ]

    这样我们的结尾就只能是三位数字

    说明:

    • urlpatterns中的元素按照顺序从上往下逐一匹配正则表达式,一旦匹配成功则不在往下匹配
    • 不需要添加一个前面的反斜杠,因为每个URL都有,例如 ^login而不是 ^/login
    • 每个正则表达式前面的‘r’是可选的,但是建议写上
    • Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加'/'。如果不需要,在settings.py配置文件中设置APPEND_SLASH  = FALSE
    • 若要从URL中获取一个值,只需要用正则里的分组匹配

    分组匹配

    在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式。

    在之前写的删除图书的时候,我们需要获取书的id,当时我们是这样写的,我们获取到id的值后传递给了id

    <a href="/delete_book/?id={{ book.id }}">删除</a>

    现在我们可以使用分组匹配来改写一下,首先是改写urls.py

    原来的路由

    url(r'^delete_book/', views.delete_book),  # 删除图书

    改成分组匹配的路由

    url(r'^delete_book/(d+)/', views.delete_book),  # 删除图书

    对应的html也要改,直接去掉?id=就可以了

    <a href="/delete_book/{{ book.id }}">删除</a>

    然后我们点击删除,发现页面报错了

    报错信息告诉我们需要一个位置参数,但给了两个,那我们去看看对应的函数是怎么写的

    #删除图书
    def delete_book(request):
        delete_book_id = request.GET.get('id')
        Book.objects.filter(id=delete_book_id).delete()
        return redirect('/book_list/')

    函数接收一个参数没错呀,为什么报错信息提示我们给了两个参数?这是因为Django会把分组匹配里的内容当做一个参数传给对应的函数,这样我们就不需要从url里获取书的id值了,函数直接接收就行了,在来修改下我们的函数

    def delete_book(request, delete_book_id):
        # delete_book_id = request.GET.get('id')
        Book.objects.filter(id=delete_book_id).delete()
        return redirect('/book_list/')

    这样我们就能正常删除了,书的id传给了参数delete_book_id这个参数

    除了上面的这种写法,我们还可以给分组起个名称,然后再函数里接收这个参数

    在修改URL

    url(r'^delete_book/(?P<book_id>d+)/', views.delete_book),  # 删除图书

    在去删除图书,发现页面又报错了

    报错信息告诉我们,得到了一个意外的关键字参数book_id,这是因为,如果是分组命名的话,django会把我们起的名称以关键字(字典)的形式传给对应的函数,那我们把之前函数里写的 delete_book_id参数名改为book_id就可以了

    #删除图书
    def delete_book(request, book_id):
        # delete_book_id = request.GET.get('id')
        Book.objects.filter(id=book_id).delete()
        return redirect('/book_list/')

    注意:

    URL在匹配的时候,只匹配路径,也就是说?和后面的参数都不匹配

    路由不检查请求方式,也就是说,get,post,delete,put等,只要是同一个路径,都会匹配到同一个函数

    只要是正则表达式匹配的,获得的参数永远都是字符串(除非你自己转)

     include(路由分发)

    之前我们的路由都是写在项目里的urls.py里面,但是我们的项目可能会越来越大,如果都写在一个py文件里,以后找起来也很麻烦,那有没有更好的方法呢?之前说app的时候,我们知道我们可以把一个模块或功能放在一个app里面,那我们可以把对应这个模块的路由也放在对应的app下面,这样我们找起来就很容易了

    在之前appTest01的app下创建一个urls.py文件,把相关的路由放到这里面

    虽然这样改了,但是查找还是要在项目的urls.py里面进行查找,这时我们在项目里的urls.py里加上下面这句代码,让去appTest01下面去找,记得最后加"/"

    from django.conf.urls import url,include
    
    
    urlpatterns = [
       
        url(r'^appTest01/', include('appTest01.urls')),
    ]

    改了之后,我们对应的请求也要改,要在前面加上app名,如

    http://127.0.0.1:8080/appTest01/book_list/

    这样我们访问之后,先去项目的urls.py找对应的的appTest01,找到之后,在去include里的urls里面找,这种方法叫路由分发

    路由传递参数

    在上面说路由的格式的时候,说可以给路由写参数,可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。

    urlpatterns = [
         url(正则表达式, views视图,参数,别名),
    ]

    例如:

    from django.conf.urls import url
    from . import views
    
    urlpatterns = [
        url(r'^login/', views.login, {'job': 'IT'}), ]

    当请求访问login时,会给对应的函数传递一个关键字参数,如果额外传的这个关键字参数和URL中分组命名传的参数同名时,函数则使用额外给的这个参数,而不是URL中的参数

    URL反向解析(别名)

    我们之前的URL都是写死的,假如有一天,你看着这个URL名不爽了,然后你把这个名词换了一个,这时候你就要把所有引用到的这个URL都要改过来,又过了一段时间,你又觉着不爽。。。

    Django提供了我们一种给URL起别名的方式。别名就是给URL起了一个名字,通过这个名字反向拿到了URL地址。以后你如果看URL不爽了,你只需要改路由里的一个就可以了,其他引用的地方都使用这个别名就不需要改了

    例子;

    url(r'^press_list/', views.press_list, name='press'),  # 给url起了个别名为press

    在视图函数里可以这样引用

    from django.urls import reverse
    
    def press_list(request):
        ret = Press.objects.all()  
        print(reverse('press'))
    
     
        return redirect(reverse('press'))  # 通过别名去找对应的URL

    结果:

    /press_list/

    拿到的就是URL前面的路径,所以不管你urls.py里怎么改,这里都不需要改

    在模版里这么引用

    {% url 'press' %}
    分组匹配的别名

    之前在写正则表达式的时候,写了正则匹配的一个路由

    urlpatterns = [
    
        url(r'^login/([0-9]{2})/([0-9]{3})', views.login, name='home'),
    ]

    如果是通过正则表达式写的话,则需要传递参数,不传会报错

    在views.py里引用

    from django.urls import reverse
    
    reverse("home", args=("11","222" ))  # 前面是两个数字,后面是三个数字,随便写

    在模版中的引用

    {%  url 'home' '22' '333' %}
    分组命名的别名

    路由:

    url(r'^delete_book/(?P<book_id>[0-9]{4})/(?P<press_id>[0-9]{2})/', views.delete_book, name='home')

    在视图中的引用有两种方式,一种是上面的方式

    reverse("home", args=("2019","07" ))

    另一种方式

    reverse("home", kwargs={"book_id":"2019","press_id":"07"})

    在模版中引用也有两种方式,第一种,数字随便写,只要符合上面的正则表达式就行

    {%  url 'home' '2011' '33' %}

    另一种:前面的名称要和路由里起的名称一样

    {%  url 'home' book_id='2011' press_id='33' %}

    命名空间

    假如我们有多个app,并且每个app下都有一个别名,name=’home‘

    urlpatterns = [
    
        url(r'^appTest01/', include('appTest01.urls')),
        url(r'^appTest02/', include('appTest02.urls')),
    ]

    appTest01下的和appTest02下的别名都是一样的,如下

    url(r'^author_list/', views.author_list, name='home'),

    这时我们去打印别名,前面的路径都是appTest02,因为appTest02在下面,把上面的覆盖了

    /appTest02/author_list/

    这时候我们就需要在项目的urls.py里加上命名空间

    urlpatterns = [
    
        url(r'^login/[0-9]{2}/[0-9]{3}$', views.login),
        url(r'^appTest01/', include('appTest01.urls', namespace='appTest01')),
        url(r'^appTest02/', include('appTest02.urls', namespace='appTest01')),
    ]

    在视图中使用

    reverse("appTest01:home", kwargs={"book_id":"2019","press_id":"07"})
    
    或者
    
    reverse("appTest02:home", kwargs={"book_id":"2019","press_id":"07"})

    在模版中使用

    {%  url 'appTest01:home' '2011' '33' %}
    
    或者
    
    {%  url 'appTest02:home' '2011' '33' %}
  • 相关阅读:
    不同数据库中两列字段相减(某列有空值)
    ASP.Net MVC利用NPOI导入导出Excel
    ASP.Net MVC中数据库数据导出Excel,供HTTP下载(转)
    Asp.net操作Excel(终极方法NPOI)(转)
    开发中可能会用到的几个 jQuery 小提示和技巧(转)
    最火的.NET开源项目(转)
    sql行转列和列转行(转)
    run fsck manually
    RTP-实时协议
    linux环境几个特殊的shell变量
  • 原文地址:https://www.cnblogs.com/zouzou-busy/p/11204390.html
Copyright © 2011-2022 走看看