反向解析 无名分组 有名分组

97zs / 2024-03-06 / 原文

无名分组与有名分组

有名分组和无名分组都是为了获取路径中的参数,并传递给视图函数,区别在于无名分组是以位置参数的形式传递,有名分组是以关键字参数的形式传递。

强调:无名分组和有名分组不要混合使用

无名分组

分组:就是给某一段正则表达式用小括号扩起来

无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

 

有什么作用
可以从url地址中解析出参数,传递给视图函数使用

 urls.py:

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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    # 下述正则表达式会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以位置参数的形式传给视图函数,有几个分组就传几个位置参数
    url(r'^aritcle/(\d+)/$',views.article), 
]

  

 views.py:

from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参用于接收传递过来的分组数据
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容...' %article_id)

  测试:python manage.py runserver 8001   # 在浏览器输入:http://127.0.0.1:8001/article/3/

 

 

有名分组

可以给正则表达式起一个别名,有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数

urls.py

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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    # 该正则会匹配url地址的路径部分为:article/数字/,匹配成功的分组部分会以关键字参数(article_id=匹配成功的数字)的形式
传给视图函数,有几个有名分组就会传几个关键字参数 url(r'^aritcle/(?P<article_id>\d+)/$',views.article), ]

  views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse

# 需要额外增加一个形参,形参名必须为article_id
def article(request,article_id):
    return HttpResponse('id为 %s 的文章内容...' %article_id)

测试:python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/article/3/

 

 

同一个分组可以使用N多次
"""

# 单个的分组可以使用多次
url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),

 

 

案例
# 这种地址,把人名和id分出来
# 有名分组
# ilovejaney/p/13748739.html
url(r'^(?P<name>.*?)/p/(?P<id>\d+).html', views.article),
# 无名分组
url(r'^(.*?)/p/(\d+).html', views.article),

# 5 伪静态
-原来是动态页面/login 做成/login.html 伪装成静态页面,便于seo优化
-seo优化:

 

 

 

 

 

 反向解析:

# 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数

# 先给路由与视图函数起一个别名

案例:登录成功跳转到index.html页面

在urls.py文件中

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    url(r'^login/$', views.login,name='login_page'), # 路径login/的别名为login_page
    url(r'^index/$', views.index,name='index_page'), # 路径index/的别名为index_page

 


在views.py中

from django.shortcuts import render 
from django.shortcuts import reverse # 用于反向解析
from django.shortcuts import redirect #用于重定向页面
from django.shortcuts import HttpResponse

def login(request):
    if request.method == 'GET':
        # 当为get请求时,返回login.html页面,页面中的{% url 'login_page' %}会被反向解析成路径:/login/
        return render(request, 'login.html')
    
    # 当为post请求时,可以从request.POST中取出请求体的数据
    name = request.POST.get('name')
    pwd = request.POST.get('pwd')
    if name == 'kevin' and pwd == '123':
        url = reverse('index_page')  # reverse会将别名'index_page'反向解析成路径:/index/       
        return redirect(url) # 重定向到/index/
    else:
        return HttpResponse('用户名或密码错误')


def index(request):
    return render(request, 'index.html')

 

 

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<!--强调:login_page必须加引号-->
<form action="{% url 'login_page' %}" method="post">
    {% csrf_token %} <!--强调:必须加上这一行,后续我们会详细介绍-->
    <p>用户名:<input type="text" name="name"></p>
    <p>密码:<input type="password" name="pwd"></p>
    <p><input type="submit" value="提交"></p>

</form>
</body>
</html>

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h3>我是index页面...</h3>
</body>
</html>

测试

python manage.py runserver 8001  
# 在浏览器输入:http://127.0.0.1:8001/login/ 会看到登录页面,输入正确的用户名密码会跳转到index.html
# 当我们修改路由表中匹配路径的正则表达式时,程序其余部分均无需修改

总结

在views.py中,反向解析的使用:
    url = reverse('index_page')
在模版login.html文件中,反向解析的使用
    {% url 'login_page' %}

 

 

 

名称空间:

在views.py中,反向解析的使用: url = reverse('index_page') 在模版login.html文件中,反向解析的使用 {% url 'login_page' %}

解决这个问题的方法之一就是避免使用相同的别名,如果就想使用相同的别名,那就需要用到django中名称空间的概念,将别名放到不同的名称空间中,这样即便是出现重复,彼此也不会冲突,具体做法如下

1、总urls.py在路由分发时,指定名称空间

from django.conf.urls import url, include
from django.contrib import admin

# 总路由表
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    # 传给include功能一个元组,元组的第一个值是路由分发的地址,第二个值则是我们为名称空间起的名字
    url(r'^app01/', include(('app01.urls','app01'))),
    url(r'^app02/', include(('app02.urls','app02'))),
]

 

2、修改每个app下的view.py中视图函数,针对不同名称空间中的别名'index_page'做反向解析

app01下的views.py

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

def index(request):
    url=reverse('app01:index_page') # 解析的是名称空间app01下的别名'index_page'
    return HttpResponse('app01的index页面,反向解析结果为%s' %url)

 

app02下的views.py

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

def index(request):
    url=reverse('app02:index_page') # 解析的是名称空间app02下的别名'index_page'
    return HttpResponse('app02的index页面,反向解析结果为%s' %url)

 

在每个app下手动创建urls.py来存放自己的路由,并且为匹配的路径起别名



app01下的urls.py文件

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

urlpatterns = [
    # 为匹配的路径app01/index/起别名'index_page'
    url(r'^index/$',views.index,name='index_page'), 
]







app02下的urls.py文件

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

urlpatterns = [
    # 为匹配的路径app02/index/起别名'index_page',与app01中的别名相同
    url(r'^index/$',views.index,name='index_page'), 
]

 



4 有什么作用
-动态根据路由别名获得路径,一旦路径改变,不需要改其他代码

1、在视图函数中基于名称空间的反向解析,用法如下

url=reverse('名称空间的名字:待解析的别名')

2、在模版里基于名称空间的反向解析,用法如下

<a href="{% url '名称空间的名字:待解析的别名'%}">哈哈</a>