路由匹配

根据用户请求的 URL 链接来判断对应的处理程序,并返回处理结果,也就是 URL 与 Django 的视图建立映射关系。Django 路由在 urls.py 配置,urls.py 中的每一条配置对应相应的处理方法。

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/$', views.index),  # url方法的第一个参数是一个正则表达式
    url(r'^$', views.home),  # 用户不携带后缀直接访问的页面
      
]
  • django二次追加斜杠机制,首次匹配不上,那么django还会让浏览器默认加斜杠再次发送请求
  • 斜杠机制可以取消 但是不推荐 APPEND_SLASH = False

无名分组

urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
        url(r'^test/([0-9]{4})/$'),
]

​ 路由匹配成功之后就会调用视图函数,默认情况下会自动给视图函数传递一个request位置参数,如果路由匹配中使用括号对正则表达式进行了分组,那么在调用视图函数的时候,会将括号内匹配到的内容当做位置参数传递给视图函数

views.py

from django.shortcuts import render, HttpResponse, redirect

def test(response, num):  # 形参num可以是任意的
    print(num)  # 括号内正则表达式匹配到的内容
    return HttpResponse('test')

有名分组

urls.py

urlpatterns = [
    url(r"^test/(?P<sid>[0-9]{4})", views.test),
]

有名分组按关键字传参,与位置顺序无关, views 中的形参名称要与 urls 中的组名对应。无名有名分组不能在一起混合使用

views.py

def test(response, sid):  # 使用有名分组时,视图函数的形参名字必须与有名分组的名字一致
    print(sid)  # 括号内正则表达式匹配到的内容
    return HttpResponse('test')

提示

有名分组和无名分组不能同时使用,但是每一种分组可以重复使用多次,同时在视图函数中必须有对应数量的形参进行值的接收。

url(r'test/(\d+)/(\d+)/(\d+)',views.test)
url(r'test/(?P<id1>\d+)/(?P<id2>\d+)/(?P<id3>\d+)', views.test)

反向解析

每一个视图对应路由,但是匹配的关系发生了变化,对应的访问地址也发生了变化。可以通过一种动态解析url的方法来避免,使用url提供的name属性给对应路由起别名,从而让与之对应的链接或跳转,根据别名动态解析url,这个动态解析url路径的过程就是反向解析

基本反向解析

urls.py

urlpatterns = [
    url('^index/',views.index),
    url('^test/', views.test, name='test_view'),
]

index.html

<a href="{% url 'test_view' %}">test_view</a>

views.py

from django.shortcuts import render, HttpResponse, redirect, reverse


def index(request):
    print(reverse('test_view'))  # 后端通过反向解析拿到名字
    return render(response, 'index.html')


def test(request):
    return HttpResponse('from test view')

无名分组反向解析

urls.py

urlpatterns = [
    url(r'^index/',views.index),
    url(r'^test/(\d+)/', views.test, name='test_view'),
]

index.html

<a href="{% url 'test_view' 123 %}">test_view</a>

views.py

from django.shortcuts import render, HttpResponse, redirect, reverse


def index(request):
    print(reverse('test_view', args=(666,)))
    return render(response, 'index.html')


def test(response, *args, **kwargs):
    return HttpResponse('from test view') 

有名分组反向解析

urls.py

urlpatterns = [
    url(r'^index/',views.index),
    url(r'^test/(?P<id>\d+)/', views.test, name='test_view'),
]

index.html

<a href="{% url 'test_view' id=123 %}">test_view</a>

views.py

from django.shortcuts import render, HttpResponse, redirect, reverse


def index(request):
    print(reverse('test_view', kwargs={'id': 666}))
    return render(response, 'index.html')


def test(response, *args, **kwargs):
    return HttpResponse('from test view')

补充:无名有名反向解析中的手动传值,一般情况下这个值可以是数据的主键值、页面的页码、区域的编号等

路由分发

在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。

urls.py(总路由)

from django.conf.urls import url, include

# 注意不能以$结尾
urlpatterns = [
    url(r'^app01/', include('app01.urls')),
    url(r'^app01/', include('app02.urls')),
]

app01下的urls.py文件

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/$', views.index,name='app01_index_view'),
]

app01下的view.py文件

from django.shortcuts import render, HttpResponse
from django.urls import reverse


# Create your views here.
def index(request):
    url = reverse('app01_index_view')
    return HttpResponse('app01的index页面,反向解析结果为%s' % url)

app02下的urls.py文件

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^index/$', views.index,name='app02_index_view'),
]

app02下的view.py文件

from django.shortcuts import render, HttpResponse
from django.urls import reverse


# Create your views here.
def index(request):
    url = reverse('app02_index_view')
    return HttpResponse('app02的index页面,反向解析结果为%s' % url)

名称空间

不同的应用使用了相同的别名name,导致反向解析会覆盖其他应用下别名的解析。解决这个问题的方法之一就是避免使用相同的别名,如果非要使用相同的别名,那就需要用到django中名称空间的概念,将别名放到不同的名称空间中,这样即便是出现重复,彼此也不会冲突。

urls.py(总路由)

from django.conf.urls import url, include

urlpatterns = [
    url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app02/', include('app02.urls',namespace='app02')),
]

app01下的views.py

from django.shortcuts import render, HttpResponse
from django.urls import reverse


# Create your views here.
def index(request):
    url = reverse('app01:index_view')
    return HttpResponse('app01的index页面,反向解析结果为%s' % url)

app02下的views.py

from django.shortcuts import render, HttpResponse
from django.urls import reverse


# Create your views here.
def index(request):
    url = reverse('app02:index_view')
    return HttpResponse('app02的index页面,反向解析结果为%s' % url)

在html也可以这样使用

{% url 'app01:index_view' %}

Django版本区别

2.x3.x与中,路由匹配是path(),path()第一个参数不在支持正则,是一个准确路径,可以用来解决数据类型转换的问题和正则表达式冗余的问题。如果想使用正则 也提供了方法,导入from django.urls import path,re_pathre_path用法与1.xurl完全一致

五个内置转化器

  • str:匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
  • int:匹配正整数,包括0
  • slug:匹配字母、数字、下划线以及横杠组成的字符串
  • uuid:匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00
  • path:匹配任何非空字符串,包含了路径分隔符(/),不能用"?"
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    # path('login/<int:id>', views.login),
    # path('login/<str:name>', views.login),
    path('login/<path:p>', views.login),

]
Last modification:May 29, 2022
如果觉得我的文章对你有用,请随意赞赏