• 路由系统(urls.py)


         路由系统(urls.py)   

    正则表达式匹配

    urls.py

    from django.conf.urls import url
    from . import views
    urlpatterns = [
        url(r'^articles/2003/$', views.special_case_2003),
        url(r'^articles/([0-9]{4})/$', views.year_archive),
    ]
    Django 2.0版本中的路由系统已经替换成下面的写法
    from django.urls import path
    urlpatterns = [
        path('articles/2003/', views.special_case_2003),
        path('articles/<int:year>/', views.year_archive),
        path('articles/<int:year>/<int:month>/', views.month_archive),
        path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
    ]

    1.基本格式:

    from django.conf.urls import url
    urlpatterns=[
    url(正则表达式, views视图函数,参数,别名),
    ]
    url(r'^delete_book/$', views.delete_book),#严谨起见,加结束符$
    正则表达式:一个正则表达式字符串
    views视图函数:一个可调用对象
    参数:可选的要传递给视图函数的默认参数(字典形式)
    别名:一个可选的name参数
    注意点:
    1.元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
    /delete_book/?id=5在urls中匹配到delete_book就执行函数,不再匹配?id=5
    2.若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)
    url(r'^delete_book/(d)$', views.delete_book)
    在页面请求时,必须是delete_book/num 后面必须有个数字,否则匹配不上相当于为后端穿个参数
    3.不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
    4.每个正则表达式前面的'r' 是可选的但是建议加上

    URL正向解析

    分组匹配()

    相当于给视图函数传递位置参数

    1.分组匹配:会捕获括号里的内容当做参数传给执行函数

     url(r'^delete_book/([0-9]{4})/([0-9]{2})/$', views.delete_book),
     def add_book(request):pass
     只在网页上输入/delete_book/会出错,原因是给函数传了三个参数,而函数只接收了一个
     add_book(request,arg1,arg2):pass

    2.使用分组匹配完成书籍的删除

    1.url(r'^delete_book/([0-9]+)/$',views.delete_book)
    2.def delete_book(request,del_id):
        if del_id:
            del_obj=models.Book.objects.get(id=del_id)
            del_obj.delete()
            return redirect("/book_list/")
        else:
            return HttpResponse("要删除的书籍不存在")

    3.HTML中

    <a class="btn btn-danger" href="/delete_book/{{ book.id }}">删除</a>
    在urls中查找的是/delete_book/num/,查到就执行相应函数,{{ book.id }}作为参数

    分组命名匹配

    在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。
    相当于给视图函数传递关键字参数.分组匹配和分组命名匹配不能混合使用
    url(r'^delete_book/(?P<id_code>[0-9]+)/$',views.delete_book)
    将参数的名字命为id_code,函数接收时,以关键字接收
    def delete_book(request,id_code):pass id_code也可换成**kwargs
    等同于def delete_book(request,id_code=None):pass id_code
    有id_code这个变量传过来时,id_code的值为传来的值
    这样URLconf会更加明晰且不容易产生参数顺序问题的错误

    分组匹配请求和?name=num请求总结

    1.?name=num请求:

    URLconf 在请求的URL上查找将它当做一个普通的Python字符串。不包括GET和POST参数以及域名。
    例如,http://www.example.com/myapp/ 请求中,URLconf 将查找myapp/。、
    在http://www.example.com/myapp/?id=3 请求中,URLconf 仍将查找myapp/。
    ?id=3作为一个参数封装到request中。函数只接收request一个参数
    请求将id=3以字典的形式发给后端{id:3}后端函数不需要用参数接收,使用request.GET.get
    def delete_book(request):
        print(request.GET) #<QueryDict: {'id': ['3']}>
        print(request.GET.get("id")) #3

    2.分组匹配

    而在使用个分组匹配的时候,还需要接收request之外的参数,直接接收这个参数就能用
    后端需要接收
    def delete_book(request,id):
        print(id) #接收到的参数可直接用

    3.捕获的参数永远都是字符串

    4.视图函数中指定默认值

    urlpatterns = [
        url(r'^blog/$', views.page),
        url(r'^blog/pag(?P<num>[0-9]+)/$', views.page),#只捕获括号里包的内容
    ]
    # views.py中,可以为num指定默认值
    def page(request, num="1"):
        pass
    两个URL模式指向相同的view - views.page - 但是第一个模式并没有从URL中捕获任何东西。
    如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。
    
    

    路由分发 include

    当Django中用到多个app时,用到include,
    1.新建app python manage.py startapp app01
    2.在setting中INSTALLED_APPS中添加'app01.apps.App01Config',
    3.在app01中新建urls文件,项目中的urls相当于一级路由,app01中的urls相当于二级路由
    4.在app01中的urls添加配置文件
    from django.conf.urls import url
    导入同文件中的views文件可以用 from . import views
    也可以 from app01 import views
    urlpatterns=[
        url(r'^delete_book/(?P<id_code>[0-9]+)/$',views.delete_book)
    ] 添加关系
    5.在一级路由中操作:
    需要先导入include模块 from django.conf.urls import include
    再导入app01中的urls文件 from app01 import urls
    在urlpatterns中添加对应关系:
    url(r'^app01/',include(urls)) 把app01开头的请求交给二级路由处理
    在网页上输入http://127.0.0.1:8000/delete_book/ 网页找不到,在一级路由中更没有以delete_book开头的路径
    需要加上app01 http://127.0.0.1:8000/app01/delete_book/
    6.在一级路由中导入多个app的urls时,为了区别,取别名使用
    from app01 import urls as app01_urls
    from app02 import urls as app02_urls
    url(r'^app01/',include(app01_urls))
    url(r'^app01/',include(app02_urls))
    7.也可以传递额外的参数,在二级路由中传参,以字典的形式,不常用
    如:在app01的urls中
    url(r'^house/',views.house,{"age":18})
    在执行函数中接收即可:
    def house(request,args): #如是age。则显示18
    print(args) 得到字典
    
    

    URL反向解析reserve

    简单来说就是可以给我们的URL匹配规则起个名字,一个URL匹配模式起一个名字。
    以后就不需要写死URL代码了,只需要通过名字来调用当前的URL
    url中:
    之前的格式:url(r'^book_list/$', views.book_list),
    1.使用url解析:url(r'^book_list/$', views.book_list,name="check_book"),
    HTML模板中引用:
    之前的格式:
     <a class="btn btn-danger" href="/delete_book/?id={{ book.id }}">删除</a>#}
     使用反向解析: <a class="btn btn-danger" href="{% url 'check_book' book.id %}">删除</a>#}
    views中引用使用reverse:
    return redirect("/book_list/") 重定向
     from django.urls import reverse
     def del_book(request) 
          rediret_url=reverse('check_book') 
        return redirect(rediret_url)

    总结:

    1. 怎么起别名?
    在url匹配模式中,定义name="别名"
    2. 如何使用?
    1. 在模板语言里面使用:
    {% url "别名" %} --> 得到具体的URL路径
    2. 在视图中如何使用:
    from django.urls import reverse
    reverse("别名") --> 得到具体的URL路径
    3. 如何传参数?
    1. 模板语言中:
    {% url "别名" 2018 "nb" %}
    2. 视图函数中:主要用于重定向
    def del_book(request) #不接收参数。如果使用重定向捕获到值,就需要接受参数
        传位置参数:传的是个元祖
            reverse_red=reverse("别名", args=(2018, "nb"))  #参数在这里传
            return redirect(reverse_red)
        传关键字参数:传的是字典
            reverse("别名" kwargs={"year": 2018, "title": "nb"})

    名称空间

    由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回
    不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
    
    
    project的urls.py:
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^app01/', include("app01.urls",namespace="app01")),
        url(r'^app02/', include("app02.urls",namespace="app02")),
    ]
    app01.urls:
    urlpatterns = [
        url(r'^index/', index,name="index"),
    ]
    app02.urls:
    urlpatterns = [
        url(r'^index/', index,name="index"),
    ]

    views

    app01.views 
    from django.core.urlresolvers import reverse
    def index(request):
        return  HttpResponse(reverse("app01:index"))
    app02.views
    from django.core.urlresolvers import reverse
    def index(request):
    
    

    总结

    1.请求在Django路由分配的五个步骤:    
       1.从project/urls.py(和settings是同级的)开始找起
    2.所有的urls.py都要有个urlpatterns这个变量,变量是个列表
    3.遍历上面的列表,依次匹配,如果匹配到就立即停止,调用后面的函数
    4.调用函数时可以传递参数
    5.如果整个列表都没有匹配上,就抛出异常
    2.URL正向:
         1.正则表达式里有分组匹配的话,会传位置参数

    2.正则表达式里有命名分组匹配的话,会传关键字参数
    3.直接传参数
    3.反向解析URL:给正则表达式起别名,然后根据别名反向图到处真正的URL
    4. print(request.get_full_path()) # 获取当前请求的路径和参数
    print(request.path_info) # 取当前请求的路径
     


     
     




  • 相关阅读:
    2016/05/16 thinkphp3.2.2 验证码使用
    2016/05/16 UEditor 文本编辑器 使用教程与使用方法
    2016/05/15 ThinkPHP3.2.2 表单自动验证实例 验证规则的数组 直接写在相应的控制器里
    DropzoneJS 使用指南
    MVC设计模式
    Smarty 配置文件的读取
    会话控制
    JS中的call和apply
    CSS选择器
    XML
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9219151.html
Copyright © 2020-2023  润新知