路由控制

一、Django中路由的作用

  把视图函数与特定的 URL 对应起来,要使用 URL 配置(URLconf),URL 配置把 URL 映射到相应的视图函数上。我们以这种方式告诉 Django,“访问这个URL 时调用这些代码,访问那个 URL 时调用那些代码”。

二、URL 配置

  URL 配置:urls.py 文件

# 初始urls.py文件内容
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
    url(r'^admin/', admin.site.urls),  # Django后台管理URL
]

添加URL和视图的对应关系

  变量urlpatterns负责定义 URL 与处理URL 的代码之间的映射。

from django.conf.urls import url
from django.contrib import admin  
from app import views  #从应用中导入视图函数文件,此app泛指应用名
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(正则表达式, views视图函数,参数,别名), 
]
  • 正则表达式:一个正则表达式字符串,匹配对应URL
  • views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串(CBV则写法有所改变)
  • 参数:可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选的name参数

  正则表达式字符串前面的 'r' 字符表示“原始字符串”,不会解释里面的反斜线。

  脱字符号^表示“在字符串的开头匹配模式”,如果开头没有脱字符号(即 hello/$),Django 会匹配任何以 hello/ 结尾的 URL。

  美元符号$的意思是“在字符串的结尾匹配模式”,如果使用 ˆhello/ 模式(末尾没有美元符号),那么任何以 /hello/ 开头的 URL 字符串都能匹配,使用脱字符号和美元符号确保只匹配 /hello/ 这个 URL——不多不少。

  urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。

  如果请求的 URL 不匹配任何 URL 模式,而且末尾没有斜线,那么 Django 会把它重定向(redirect)到末尾带斜线的 URL。这是Django默认的配置APPEND_SLASH=True所带来的的效果,一旦我们在settings.py配置文件中将其值改为FALSE,将不会自动在网址后面添加'/'。

三、无名分组

  将加括号的正则表达式匹配到URL中的内容当做位置参数自动传递给相应的视图函数。

url(r'^test/(\d+)/',views.test),  # \d+匹配一个或多个数字,使用圆括号从匹配的文本中捕获数据
        
def test(request,args):
    print(args)
    return HttpResponse('test')

四、有名分组

  将加括号的命名的正则表达式匹配到URL中的内容当做关键字参数自动传递给相应的视图函数。

url(r'^test/(?P<example>\d+)/',views.test),  

def test(request,example):  # 变量名必须和正则名字相同
    print(example)
    return HttpResponse('test')
  1. 有名分组和无名分组无法混合使用
  2. 支持同一类型分组,多个匹配:r'^test/(?P<year>\d+)/(?P<mouth>\d+)/(?P<day>\d+)/'

 五、反向解析

  根据名字动态获取到对应路径,应用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。

使用方法

from django.shortcuts import reverse
# 为路由与视图函数对应关系起个名字,唯一标识对应路径,名字不可重复
url(r'^indexluan/$',views.index,name='index')

前端使用

{% url '你给路由与视图函数对应关系起的别名' %}

后端使用

reverse('你给路由与视图函数对应关系起的别名')

无名分组反向解析

url(r'^test/(\d+)/',views.test,name='example')
# 后端使用
reverse('example',args=(加括号匹配到的内容,))
# 前端使用
{% url '你给路由与视图函数对应关系起的别名' 需传递的值 %}

有名分组反向解析

# 后端使用
# 后端有名分组和无名分组都可以用这种形式
reverse('example',args=(加括号匹配到的内容,))
# 下面这个了解即可
reverse('example',kwargs={加括号匹配到的内容('关键字参数':值)})
# 前端使用
# 前端有名分组和无名分组都可以用这种形式
{% url 'example' 需传递的值 %}
# 下面这个了解即可
{% url 'example' 需传递的值(关键字参数=值) %}

六、路由分发

  Django每一个app下面都可以有自己的urls.py路由层,templates文件夹,static文件夹。项目名下的urls.py(总路由)不再做路由和视图函数的匹配关系,而是做路由的分发。

1.起别名的方式避免冲突

# 总路由下
from django.conf.urls import include
from app01 import urls as app01_urls
from app02 import urls as app02_urls

# 路由分发  注意路由分发总路由千万不要$结尾
url(r'^app01/',include(app01_urls)),
url(r'^app02/',include(app02_urls))

# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系即可
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^index/',views.index)
]

2.写成字符串形式(importlib)

# 总路由下
from django.conf.urls import include

# 路由分发  注意路由分发总路由千万不要$结尾
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))

# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系即可
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^index/',views.index)
]

七、名称空间

  命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。

  由于name没有作用域,Django在反解URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回。

  我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。

错误场景

# 总路由下
from django.conf.urls import include

# 路由分发  注意路由分发总路由千万不要$结尾
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))

# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系,为其取名index
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^index/',views.index,name='index')
]

# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系,也为其取名index
from django.conf.urls import url
from app02 import views
urlpatterns = [
    url(r'^index/',views.index,name='index')
]

# app01的视图函数
def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app01')

# app02的视图函数
def index(request):
    url=reverse('index')
    print(url)
    return HttpResponse('index app02')

  这样都找index,app01和app02找到的都是app02的index

解决方案

  此时我们需要在路由分发的时候指定名称空间

# 总路由下
from django.conf.urls import include

# 路由分发  注意路由分发总路由千万不要$结尾
url(r'app01/',include('app01.urls',namespace='app01')),
url(r'app02/',include('app02.urls',namespace='app02'))

  视图函数下反向解析

# app01.views.py
url = reverse('app01:index')
    
# app02.views.py
url = reverse('app02:index')

  模板里反向解析

<a href="{% url 'app01:index'%}">解决</a>

 注:一般来说,我们会在反向解析命名的时候加以区分,例如app01下的index,我们就以name = app01_index处理。

posted on 2019-07-18 17:31  慕子尔  阅读(99)  评论(0编辑  收藏  举报

导航