在網路管理中,有效管理 IP 位址至關重要。本文將引導讀者使用 Django 框架開發一個功能完善的 IP 位址管理 Web 應用程式。從設定 URL 路由開始,逐步建立檢視函式處理使用者請求,並利用 Django 的 ORM 與資料函式庫互動,最後使用範本引擎渲染資料,呈現友善的使用者介面。同時,文章也涵蓋了新增與刪除 IP 位址記錄的功能實作,讓讀者能快速上手,開發實用的網路管理工具。
建立 IP 位址管理 Web 應用程式:檢視與呈現資料
在 Django 框架中,建立一個用於 IP 位址管理的 Web 應用程式需要定義 URL 對映規則、建立檢視函式以及使用範本來呈現資料。本章節將介紹如何實作這些功能。
定義 URL 對映規則
首先,需要定義 URL 對映規則以將請求重定向到適當的檢視函式。以下是一個範例:
urlpatterns = patterns('ip_addresses.views',
url(r'^networkaddress/$', 'display'),
url(r'^networkaddress/(?P<address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})/$',
'display'),
)
第一個規則匹配 URL /ip_address/networkaddress/ 並呼叫 display 函式。第二個規則匹配 URL /ip_address/networkaddress/a.b.c.d/x/ 並呼叫 display 函式,同時傳遞 address 引數。
建立檢視函式
接下來,需要建立一個檢視函式來處理請求並傳回回應。以下是一個簡化的 display 函式範例:
def display(request, address=None):
if not address:
msg = "Top of the address tree"
else:
msg = "Top level address: %s" % address
return HttpResponse(msg)
這個函式檢查 address 引數是否存在,如果不存在則傳回一個簡單的訊息,否則傳回包含 address 的訊息。
程式碼解析:
def display(request, address=None):
- 定義
display函式,接受request和address引數。
if not address:
msg = "Top of the address tree"
else:
msg = "Top level address: %s" % address
- 檢查
address是否存在,如果不存在則設定msg為 “Top of the address tree”,否則設定msg為包含address的字串。
return HttpResponse(msg)
- 傳回一個包含
msg的 HTTP 回應。
載入初始資料
為了測試應用程式,可以使用 Django 的 fixture 功能載入初始資料。以下是一個範例 sample_data.json 檔案:
[
{
"model": "ip_addresses.networkaddress",
"pk": 1,
"fields": {
"address": "192.168.0.0",
"network_size": 24,
"description": "First top level network"
}
},
{
"model": "ip_addresses.networkaddress",
"pk": 3,
"fields": {
"address": "192.168.0.0",
"network_size": 25,
"description": "Subnet 1-1",
"parent": 1
}
}
]
可以使用以下命令載入初始資料:
$ python manage.py loaddata sample_data.json
Installed 20 object(s) from 1 fixture(s)
$
資料載入邏輯:
- 資料以 JSON 格式儲存,每個物件代表一個
NetworkAddress例項。 - 每個物件包含
model、pk和fields三個屬性。 fields屬性中包含了該例項的各個欄位值。
使用範本呈現資料
Django 的範本引擎允許開發者將應用程式邏輯與呈現分離。以下是一個範例 display 函式,使用範本呈現資料:
def display(request, address=None):
if not address:
parent = None
else:
ip, net_size = address.split('/')
parent = NetworkAddress.objects.get(address=ip, network_size=int(net_size))
addr_list = NetworkAddress.objects.filter(parent=parent)
return render_to_response('display.html',
{'parent': parent, 'addresses_list': addr_list})
這個函式查詢資料函式庫並取得相關資料,然後使用 display.html 範本呈現資料。
程式碼解析:
if not address:
parent = None
else:
ip, net_size = address.split('/')
parent = NetworkAddress.objects.get(address=ip, network_size=int(net_size))
- 如果
address不存在,則設定parent為None。 - 否則,從
address中提取 IP 位址和網路大小,並查詢對應的NetworkAddress物件。
addr_list = NetworkAddress.objects.filter(parent=parent)
- 查詢所有父物件為
parent的NetworkAddress物件。
return render_to_response('display.html',
{'parent': parent, 'addresses_list': addr_list})
- 使用
display.html範本呈現資料,並傳遞parent和addresses_list變數。
透過以上步驟,可以建立一個基本的 IP 位址管理 Web 應用程式,並使用 Django 的範本引擎呈現資料。
建立 IP 位址管理的網頁應用程式(續)
呈現 IP 位址樹狀結構
在前面的章節中,我們已經瞭解 Django 的 URL 分發器會根據使用者的請求呼叫 display 函式,並傳入初始 IP 位址或不傳入任何引數。當使用者請求頂層列表時,display 函式不會接收到初始 IP 位址;而當使用者請求顯示子網內容時,則會傳入初始 IP 位址。
如果位址欄位為空,我們將顯示所有沒有父節點的樹狀節點;如果位址欄位不為空,我們需要取得所有父節點設定為指定位址的樹狀節點列表。這些結果將儲存在 addr_list 中,並傳遞給範本。
有兩個實體需要被顯示:當前樹狀節點的資訊及其子節點列表。因此,我們需要將這兩者作為變數傳遞給範本渲染程式。在我們的範例中,我們使用了一個名為 render_to_response 的捷徑函式,它接受兩個引數:範本檔案名稱和範本將用於渲染 HTML 輸出的變數字典。
from django.shortcuts import render_to_response
內容解密:
render_to_response是 Django 提供的一個捷徑函式,用於簡化範本渲染的過程。- 這個函式需要兩個主要引數:範本名稱和一個包含範本所需變數的字典。
- 在本範例中,範本名稱被指定為一個字串,而不需要任何前置的目錄路徑。
範本載入器與應用程式目錄
Django 的範本載入器預設在 settings.py 組態檔案中啟用,以下是預設的範本載入器:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
)
我們使用的是由 app_directories 載入器提供的功能。這個載入器會在應用程式目錄下的 templates/ 子目錄中尋找範本。將範本儲存在應用程式目錄下非常有用,因為這允許開發人員隨著每個應用程式分發一組預設範本。
因此,在我們的範例中,我們需要在 ip_addresses 應用程式目錄下建立一個名為 “templates” 的子目錄。然後,我們在該目錄下建立如清單 3-9 所示的範本,該範本負責顯示由 display 檢視函式傳遞給它的資訊。
清單 3-9:用於顯示檢視的範本
{% if parent %}
目前位址:{{ parent.address }}/{{ parent.network_size }}</h1>
<a href="../../{% if parent.parent %}{{ parent.parent.address }}/{{ parent.parent.network_size }}/{% endif %}">傳回</a></h2>
{% else %}
位於網路樹狀結構的頂層</h1>
{% endif %}
{% if addresses_list %}
<ul>
{% for address in addresses_list %}
<li><a href="{% if parent %}../../{% endif %}{{ address.address }}/{{ address.network_size }}{% ifequal address.network_size 32 %}/modify/{% endifequal %}">{{ address.address }}/{{ address.network_size }}</a>
{% ifequal address.network_size 32 %}(主機){% else %}(網路){% endifequal %}
{{ address.description }}
(<a href="{% if parent %}../../{% endif %}{{ address.address }}/{{ address.network_size }}/delete/">刪除</a> |
<a href="{% if parent %}../../{% endif %}{{ address.address }}/{{ address.network_size }}/modify/">修改</a>)
</li>
{% endfor %}
</ul>
{% else %}
{% ifequal parent.network_size 32 %}
這是一個節點 IP
{% else %}
此範圍內沒有位址或子網路
{% endifequal %}
{% endif %}
<a href="add/">新增子網路或節點 IP</a></h2>
內容解密:
- 範本語言使用
{% ... %}或{{ ... }}包圍標記,前者用於包圍命令和流程控制陳述式,後者用於顯示變數內容。 - 變數的參照遵循 Python 的慣例,例如
parent.address用於顯示parent物件的address屬性。 - 常用的範本語言結構包括條件判斷 (
if、ifequal)、迴圈 (for) 和註解 (comment)。
Django 範本語言的基本結構
表格 3-4 列出了 Django 範本語言中最常用的元素。
| 結構 | 描述 |
|---|---|
{% if <variable> %} ... {% else %} ... {% endif %} | 用於測試變數是否已定義且內容不為空。 |
{% for <variable> in <list> %} ... {% endfor %} | 用於迴圈遍歷列表中的所有專案。 |
{% ifequal <variable1> <variable2> %} ... {% else %} ... {% endifequal %} | 用於比較兩個變數並根據結果處理不同的範本區塊。 |
{% comment %} ... {% endcomment %} | 用於註解掉範本中的某些部分。 |
內容解密:
- 這些結構使得範本能夠根據變數的值動態地生成內容。
- 使用這些結構可以使範本更加靈活和可重用。
網頁應用程式介面
圖 3-4 展示了當我們瀏覽到其中一個預先建立的網路位址時,應用程式網頁的外觀。
內容解密:
- 圖 3-4 直觀地展示了應用程式的使用者介面。
- 使用者可以透過這個介面瀏覽、新增、修改和刪除網路位址。
在IP位址管理Web應用程式中實作記錄刪除與新增功能
在建立IP位址管理系統時,刪除和新增記錄是兩個重要的功能。本章節將探討如何在Django框架中實作這兩個功能。
刪除記錄
首先,我們需要在urls.py檔案中新增一個URL規則,以便Django能夠識別刪除記錄的URL並呼叫相應的檢視函式。
url(r'^networkaddress/(?P<address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2})/delete/$', 'delete'),
刪除檢視函式實作
def delete(request, address=None):
ip, net_size = address.split('/')
parent = NetworkAddress.objects.get(address=ip, network_size=int(net_size)).parent
NetworkAddress.objects.get(address=ip, network_size=int(net_size)).delete()
redirect_to = '../../../'
if parent:
redirect_to += '%s/%s/' % (parent.address, int(parent.network_size))
return HttpResponseRedirect(redirect_to)
內容解密:
- 引數解析:函式接收
request和address兩個引數,其中address包含IP位址和網路大小。 - 分割IP位址和網路大小:使用
split('/')方法將address分割成IP位址和網路大小。 - 查詢父物件:根據IP位址和網路大小查詢其父物件。
- 刪除記錄:呼叫
delete()方法刪除指定的記錄。Django會自動處理相關子物件的刪除。 - 重新導向:根據父物件的存在與否,決定重新導向的URL。
新增記錄
新增記錄涉及使用者輸入,因此需要定義表單類別。
定義表單類別
from django.forms import ModelForm
class NetworkAddressAddForm(ModelForm):
class Meta:
model = NetworkAddress
exclude = ('parent', )
內容解密:
- 表單類別定義:使用
ModelForm建立一個根據NetworkAddress模型的表單。 exclude屬性:排除parent欄位,因為它將根據目前的URL自動指定。
新增檢視函式實作
def add(request, address=None):
if request.method == 'POST':
parent = None
if address:
ip, net_size = address.split('/')
parent = NetworkAddress.objects.get(address=ip, network_size=int(net_size))
new_address = NetworkAddress(parent=parent)
form = NetworkAddressAddForm(request.POST, instance=new_address)
if form.is_valid():
form.save()
return HttpResponseRedirect("..")
else:
form = NetworkAddressAddForm()
return render_to_response('add.html', {'form': form,}, context_instance=RequestContext(request))
內容解密:
- 請求方法判斷:根據請求方法是
POST還是GET進行不同的處理。 POST請求處理:驗證表單資料的有效性,如果有效則儲存新記錄並重新導向。GET請求處理:顯示空白表單。- 父物件指定:根據URL中的地址資訊查詢父物件並指定給新記錄。
重點回顧
- 在Django中實作記錄的刪除和新增功能,需要定義相應的URL規則和檢視函式。
- 刪除功能涉及查詢相關記錄並呼叫其
delete()方法,Django會自動處理相關子物件的刪除。 - 新增功能需要定義表單類別,並在檢視函式中處理表單資料的驗證和儲存。