python_fullstack—Django框架(四)-Django URLConf

Django URL分发 & 反向解析

一、URL分发

1、Django如何处理一个请求

  • Django决定要使用的根URLConf,这个根URLConf通常是由ROOT_URLCONF设置的,但是如果传入的HttpRequest对象有urlconf参数的话,它会取代ROOT_URLCONF。
  • Django会读取urlpatterns变量,变量应该是django.conf.urls.url()对象的列表集合
  • Django会逐条匹配URL,会返回匹配到的第一条请求URL
  • 一旦成功匹配了正则表达式,Django会引入对应的view方法,view的参数如下:
    • HttpRequest对象
    • 如果匹配到的正则表达式没有返回命名组,则正则表达式中的匹配项作为位置参数提供
    • 关键字参数由匹配到的正则表达式中的命名组组成, 并且通过kwargs参数重写django.conf.urls.url()
  • 如果没有匹配的正则表达式,或者在处理过程中抛出了异常,Django会调用适当的错误处理视图

2、注意点

2.1 分组和命名分组不能同时使用
# 请求URL
http://127.0.0.1:8000/kwargs_test/123/abc/

# urls.py
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test)

# 视图views.py
def kwargs_test(request, *args, **kwargs):
    print(args, kwargs)
    return HttpResponse("OK")

# 输出
() {'name': 'abc',}
2.2 django.conf.urls.url()的关键字参数会覆盖正则表达式中命名分组捕获的值
#请求URL
http://127.0.0.1:8000/kwargs_test/123/abc/

# urls.py
url(r'^kwargs_test/(\d+)/(?P<name>\w+)/', views.kwargs_test, {"new_name": "Yang"}),

# 视图views.py
def kwargs_test(request, *args, **kwargs):
    print(args, kwargs)
    return HttpResponse("OK")

# 输出
() {'name': 'abc', 'name1': 'Q1mi'}
2.3 向视图函数传递参数三种方法
  1. 在正则匹配模式中使用分组模式从请求的URL中捕获参数并以位置参数的形式传递给视图
  2. 在正则匹配模式中使用命名分组模式从请求的URL中捕获参数并以关键字参数的形式传递给视图
  3. 通过给django.conf.urls.url()传递参数

二、URL反向解析

在我们的Django项目中,我们经常会遇到要在视图中返回一个重定向到具体URL的响应,或者要将具体的URL地址嵌入到HTML页面中(如:a标签的href属性等)的情况,Django框架充分考虑了这种需求,所以提供了工具来反向解析(推导)出具体的URL。

1. name模式

在Django的URLconf中,我们可以通过给匹配模式起别名,然后我们可以通过别名来反向推导出具体的URL。

1.1 普通情况
# urls.py
urlpatterns = [
    # 为匹配模式起别名
    url(r'^student_list/', views.student_list, name="students"),
]

# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from django.urls import reverse
def add_student(request):
    if request.method == "POST":
        # 根据别名反向推导出具体的URL,避免出现硬编码URL的情况。
        url = reverse("students")  # 得到URL: /student_list/
        return redirect(url)

# HTML中
<a href="{% url 'students' %}">点击查看所有学生信息</a>
1.2 URL中需要位置参数
# urls.py
urlpatterns = [
    # 为匹配模式起别名,并且正则表达式中有分组匹配
    url(r'^student/(\d+)', views.student_detail, name="student_detail"),
]

# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from django.urls import reverse
def add_student(request):
    if request.method == "POST":
        # 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
        url = reverse("student_detail", args=(1,))  # 得到URL:/student/1/
        return redirect(url)

# HTML中
<a href="{% url 'student_detail' 1 %}">点击查看学生详细信息</a>
1.3 URL中需要关键字参数
# urls.py
urlpatterns = [
    # 为匹配模式起别名,并且正则表达式中有分组匹配
    url(r'^student/(?P<num>\d+)', views.student_detail, name="student_detail"),
]

# 视图views.py中通过使用django.urls.reverse根据上面的别名反向推导出URL
from django.urls import reverse
def add_student(request):
    if request.method == "POST":
        # 根据别名和位置参数反向推导出具体的URL,避免出现硬编码URL的情况。
        # 得到URL:/student/10/
        url = reverse("student_detail", kwargs={"num": 10})
        return redirect(url)

# HTML中
<a href="{% url 'student_detail' num=10 %}">点击查看学生详细信息</a>

2. namespace模式

我们的项目比较庞大,其URL可能成百上千,不可避免的会出现别名重复的情况。这个时候就需要使用namespace了,我们可以为不同的urlpatterns设置一个namespace(命名空间),这样在不同的命名空间下即使别名相同,还是可以通过namespace来区分不同的URL匹配模式。

# urls.py中
urlpatterns = [
    # 为app01.urls设置命名空间名:beijing
    url(r'^beijing/', include("app01.urls", namespace="beijing")),
    # 为app02.urls设置命名空间名:shanghai
    url(r'^shanghai/', include("app02.urls", namespace="shanghai")),
]

# app01/urls.py
urlpatterns = [
    # app01/urls.py中有一个别名为index的匹配模式
    url(r'^index/$', views.index, name="index"),
]

# app02/urls.py
urlpatterns = [
    # app02/urls.py中也有一个别名为index的匹配模式
    url(r'^index/$', views.index, name="index"),
]

# 视图views.py中
def index(request):
    # 通过 namespce:name 的方式来反向推导出准确的URL
    url = reverse("shanghai:index")

# HTML中
<a href="{% url 'shanghai:index' %}">上海分公司首页</a>
2.1 也可以通过在app/urls.py中定义app_name来设置app级别的namespace
# 在上面示例的app01/urls.py文件中:

app_name = "beijing"
urlpatterns = [
    url(r'^index/$', views.index, name="index"),
]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值