六.Django中URL的引數傳遞
在Django中有非常強大的URL模組,可以按照開發者的想法來制定清晰的URL,同時支援正則表示式。此外,在URL中還可以傳遞引數。
1. Django處理請求的方式
1) Django通過URLconf模組來進行判斷。通常情況下,這就是ROOT_URLCONF配置的價值,但是如果請求攜帶了一個urlconf的屬性(通常被中介軟體設定),那麼這個被攜帶的urlconf將會替代ROOT_URLCONF的配置。
2) Django會呼叫Python模組並尋找各種urlpatterns。這是一個屬於django.conf.urls.url()例項的python列表。
3) Django會遍歷每個URL pattern,自上而下,並且選取收割匹配請求URL的pattern。
4) 一旦匹配某個url pattern的正則表示式,Django將匯入並呼叫相關的view(這是一個簡單的python函式,或者是一個class-based view)
這個view將會傳遞下列引數:
l 一個HttpRequest的例項
l 如果匹配了URL中一個no named group,那麼引數將會按根據URL中的位置一一對應
l 如果匹配了URL中一個named group,且引數傳遞是通過named group來匹配的,那麼引數將會被指定的kwargs代替。
5) 如果沒有任何一個正則表示式被匹配,那麼Django會丟擲異常,並報錯。
2. URL中的named group
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
那麼year,month將會對應views傳遞過來的year,month的值,而後面緊跟的則代表正則表達匹配的模式。
3.URL的反向解析
通常來說在處理完一個表單之後,網頁會發生跳轉。通常寫URL我們都避免硬編碼,這樣不方便後期的調整。通常我們需要從URL獲取兩種內容,最主要是view能夠通過URL獲取一些標識並處理,另一些資訊則是傳遞過來的引數。
Django提供了一種解決方案,URL mapper是與URL設計一一對應。你可以通過URLconf來實現,並反向使用它。例如,
- 由使用者通過瀏覽器發起URL請求,呼叫view,並將URL中的引數傳遞給view
- 通過view並附上相應引數,找到相應匹配的URL。
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
Django在不同的層次也提供了一些工具來實現URL的反向解析。
- 在template中:使用url標籤
- 在python中:使用django.core.urlresolvers.reverse()函式
- 在更高層次處理model例項時,可以使用get_absolute_url()方法
對於資訊系統,我們可以把Node,Device, Line都看成是一種資源,對其中任何一種要素的修改,都是對資源的修改,只是會落實到不同的表中,但是在程式中可以一樣看到。現在,我們就基於上一節的程式碼做些修改。
1)修改URL的配置,將原來的add對應的url進行擴充
urls.py:
from django.conf.urls import url
from django.contrib import admin
import echo.views
urlpatterns = [
url(r'^admin/', admin.site.urls),
#內容顯示,並通過定義name,來進行反向解析
url(r'^lists/(?P<table>\w+)/$', echo.views.lists, name='lists'),
#增加內容
url(r'^add/(?P<table>\w+)/$', echo.views.add, name='add'),
]
2) 修改views的函式的引數,在request後加入table,使該函式能夠用於所有表格。request是views函式中必須要有的引數。
views.py:
# -*- coding: UTF-8 -*-
from .models import Node,Line,Device
from forms import NodeForm,LineForm,DeviceForm
from django.shortcuts import render, redirect
# Create your views here.
def lists(request, table):
#從根據不同的請求,來獲取相應的資料,並跳轉至相應頁面
if table == 'node':
data = Node.objects.all()
list_template = 'node_list.html'
if table == 'line':
data = Line.objects.all()
list_template = 'line_list.html'
if table == 'device':
data = Device.objects.all()
list_template = 'device_list.html'
#建立context字典,將值傳遞到相應頁面
context = {
'data': data,
}
#跳轉到相應頁面,並將值傳遞過去
return render(request,list_template,context)
def add(request, table):
#根據提交的請求不同,獲取來自不同Form的表單資料
if table == 'node':
form = NodeForm(request.POST or None)
if table == 'line':
form = LineForm(request.POST or None)
if table == 'device':
form = DeviceForm(request.POST or None)
#判斷form是否有效
if form.is_valid():
#建立例項,需要做些資料處理,暫不做儲存
instance = form.save(commit=False)
#將登入使用者作為登記人
if table == 'node':
instance.node_signer = request.user
if table == 'line':
instance.line_signer = request.user
if table == 'device':
instance.device_signer = request.user
#儲存該例項
instance.save()
#跳轉至列表頁面,配合table引數,進行URL的反向解析
return redirect('lists', table=table)
#建立context來集中處理需要傳遞到頁面的資料
context = {
'form': form,
}
#如果沒有有效提交,則仍留在原來頁面
return render(request, 'add.html', context)
3)在template中建立相關頁面:
add.html:
<pre name="code" class="html"><!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form method='POST' action=''>{% csrf_token %}
{{ form }}
<input type='submit' value='提交' />
</form>
</body>
</html>
device_list.html:
<pre name="code" class="html"><!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<table>
<tr>
<th>裝置名稱</th>
<th>裝置型號</th>
</tr>
{% for item in data %}
<tr>
<td>{{ item.device_caption }}</td>
<td>{{ item.device_type }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
line_list.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<table>
<tr>
<th>線路名稱</th>
<th>線路速率</th>
<th>線路型別</th>
</tr>
{% for item in data %}
<tr>
<td>{{ item.line_code }}</td>
<td>{{ item.line_speed }}</td>
<td>{{ item.line_type }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
node_list.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<table>
<tr>
<th>節點名稱</th>
<th>節點地址</th>
<th>節點型別</th>
</tr>
{% for item in data %}
<tr>
<td>{{ item.node_name }}</td>
<td>{{ item.node_address }}</td>
<td>{{ item.node_type }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>