Django路由控制

Django路由控制

1. Django中路由的作用

  • Django中,url路由的作用,就是将客户端请求的URL,映射到对应的视图函数,并且调用这个视图函数
  • 路由的特点是,从上到下依次匹配,只要匹配上了,就不会再往后匹配
# urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^add_publish/', views.add_publish),
]

2. 路由简单的正则匹配

  • 路由中的路由路径可以使用正则表达式进行匹配
urlpatterns = [
    url(r'^test/$',views.test),  # 表示路由路径以test开头,以test/结尾,其他都不可以
    url(r'^test/\w+$', views.test), # test后连续的字母数字下划线都可以

    # 表示匹配所有,要写在所有路由后,一般用于,跳转到首页或404
    url(r'',views.test)  
]

# settings中配置添加,False表示不自动添加斜杠,再带后缀斜杠,就不能匹配了
APPEND_SLASH=False

3. 无名分组

  • 分组也是正则匹配

3.1 正则表达式分组举例

import re

res = re.search('test/([0-9]{4})/([0-9]{2})','test/2018/20')
print(res.group())
print(res.group(1))
print(res.group(2))

test/2018/20
2018
20

3.2 利用正则分组接收客户端请求的参数

  • 无名分组,类似于接收实际参数
# urls.py
urlpatterns = [
    url(r'^test/([0-9]{4})/([0-9]{2})', views.test),   # 使用分组后,就需要视图函数进行接收函数
    url(r'^test/(\d+)', views.test),  # 比如请求中,带有`?nid=1` 这样的参数,直接用正则拿,不用再使用`GET.get()`方式获取了
]

# 视图函数test
def test(request,year,moth):  # 有几个参数,就要接收几个,不然会报错
    print(year)
    print(moth)
    return HttpResponse('OK')

3.2 模拟伪静态网页

  • 伪静态网页,目的就是,让搜索引擎收入SEO权限更高
  • 模拟伪静态网页,利用网页的分组实现,对SEO的网页优化
# urls.py
url(r'^test/(\d+).html', views.test)   # 客户端请求的是静态地址.html,实际映射到test视图函数

# views.py
def test(request,id):
    print(id)
    # print(moth)
    return HttpResponse('伪静态'+id+'.html文件')

# 模本
<a href="/test/?id=2.html">伪静态</a>             # 动态网页
<a href="/test/{{ book.nid }}.html">伪静态</a> # 转为伪静态网页

4. 有名分组

  • 有名分组,类似于接收关键字参数,给正则匹配出来的数据进行命名
  • 有名分组的书写格式:(?P<分组的名字>)

4.1 正则表达式有名分组举例

import re

res = re.search('test/(?P<year>[0-9]{4})/(?P<moth>[0-9]{2})','test/2018/20')
print(res.group('year'))
print(res.group('moth'))

2018
20

4.2 有名分组的使用

  • 路由中关键字的名字和视图中关键字的名字,要保持一致,否则报错,视图函数的参数位置可以颠倒
# urls.py
url(r'^test/(?P<year>[0-9]{4})/(?P<moth>[0-9]{2})', views.test)

# views.py
def test(request,year,moth):  # 捕获的分组数据,都是str数字类型
    print(year,moth)
    return HttpResponse('year:%s,moth:%s' %(year,moth))

# 有名分组可以使用`**kwargs`接收,无名分组可以使用`*args`接收,但是有名分组和无名分组不能混用
def test(request,**kwargs):
    print(kwargs)
    return HttpResponse('%s' %kwargs)

def test(request,*args):
    print(args)
    return HttpResponse('ok')

4.2 设置默认值

url(r'^test/(?P<year>[0-9]{4})/', views.test)
def test(request,year,moth=19):   # 在视图中指定默认值
    print(year,moth)
    return HttpResponse('ok')

5. 路由分发

  • 路由分发的顺序:先由总路由分发给各个app,每个app在从自己的urls.py路由中,分发视图函数,或者继续分发到下层的urls.py中,但是不推荐这样

5.1 在总的路由urls.py中导入include模块,并添加路由

# urls.py导入include模块
from django.conf.urls import url,include   

# 添加路由,方式一(推荐)
url(r'^toapp01',include('app01.urls'))

# 添加路由,方式二
from app01 import urls
url(r'^toapp01',include('urls')

5.2 在app01中创建urls.py

# app01-urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^test01',views.test01)
]

6. 反向解析

  • 反向解析:给路由url路径,其个别名
  • 反向解析的作用:用户的使用是根据别名访问的,因此修改路由路径不影响使用

6.1 反向解析在视图函数中的使用

# urls.py添加别名
url(r'^test/', views.test),
url(r'^index1/', views.index, name='aaa'),   # name=别名,通过访问aaa,反向解析到test

# views视图函数
def test(request):
    # 映射为路由url路径,即使url路径修改,aaa也能获取到修改后的url
    url=reverse('aaa')
    print(url)
    return redirect(url)   # 重定向到url,这样url重定向就写活了
    # return redirect('/index/')  # 这样就写死了

def index(request):
    return HttpResponse('index')

6.2 反向解析在前端页面中的使用

# views.py
def test(request):
    url=reverse('aaa')
    print(url)
    return render(request,'test.html')

# 模板html-test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--点击后跳转到index,但是这样就写死了,路由index一变化就不能访问了-->
{#<a href="/index/">页面的反向解析</a>#}
<!--href="{% url 'aaa' %}"这样就写活了-->
<a href="{% url 'aaa' %}">页面的反向解析</a>
</body>
</html>

6.3 无名分组带参数的反向解析

# urls.py
url(r'^test/', views.test),
url(r'^index/([0-9]{4})/([0-9]{2})', views.index, name='aaa'),

# views.py
def test(request):
    url=reverse('aaa',args=(2016,12)) # 映射后的参数也要传过来,字符串数字也可以
    print(url)
    return render(request,'test.html')

def index(request,year,month):
    return HttpResponse('index')

# test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="{% url 'aaa' 2016 11 %}">页面的反向解析</a>  # 页面上需要传参数
</body>
</html>

6.4 有名分组带参数的反向解析

# urls.py
url(r'^test/', views.test),
url(r'^index/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})', views.index, name='aaa'),

# views.py
def test(request):
    url=reverse('aaa',kwargs={'year':2012,'month':12})
    # 或者url = reverse('aaa', args=(2012,12))
    print(url)
    return render(request,'test.html')

def index(request,year,month):
    return HttpResponse('index')

# test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="{% url 'aaa' year=2016 month=11 %}">页面的反向解析</a>
<a href="{% url 'aaa' 2016 11 %}">页面的反向解析</a>  # 顺序不能颠倒
</body>
</html>

7. 名称空间

  • 指定名称空间,表示路由会从指定的名称空间中找
# urls.py 指定名称空间namespace='app01'
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02')),

# app01下的urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^test01',views.test01, name='test')  # 指定了相同的别名
]

# app02下的urls.py
from django.conf.urls import url,include
from django.contrib import admin
from app02 import views

urlpatterns = [
    url(r'^test02',views.test02, name='test')
]


# app01下的views.py
def test01(request):
    # test可以写成app01_test便于区分
    url = reverse('app01:test')  # 表示在路由分发时,只去app01找
    print(url)
    return HttpResponse('app01_test01')

# app02下的views.py
def test02(request):
    url = reverse('app02:test')  # 别名指定名称空间
    print(url)
    return HttpResponse('app02_test02')

# 模本中的名称空间
<a href="{% url 'app01:test' %}">html中名称空间的使用</a>

8. Django1.xx版本和Django2.xx版本的区别

8.1 路由上的区别

  • 1.xx的url和2.xx的re_path一样,2.xx的path不支持正则
from django.conf.urls import url,include  # 1.xx版本
from django.conf.urls import re_path,path,include   # 2.xx版本

猜你喜欢

转载自www.cnblogs.com/itone/p/9588060.html