在網路管理中,有效管理 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 函式,接受 requestaddress 引數。
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 例項。
  • 每個物件包含 modelpkfields 三個屬性。
  • 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 不存在,則設定 parentNone
  • 否則,從 address 中提取 IP 位址和網路大小,並查詢對應的 NetworkAddress 物件。
addr_list = NetworkAddress.objects.filter(parent=parent)
  • 查詢所有父物件為 parentNetworkAddress 物件。
return render_to_response('display.html',
                          {'parent': parent, 'addresses_list': addr_list})
  • 使用 display.html 範本呈現資料,並傳遞 parentaddresses_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

內容解密:

  1. render_to_response 是 Django 提供的一個捷徑函式,用於簡化範本渲染的過程。
  2. 這個函式需要兩個主要引數:範本名稱和一個包含範本所需變數的字典。
  3. 在本範例中,範本名稱被指定為一個字串,而不需要任何前置的目錄路徑。

範本載入器與應用程式目錄

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>

內容解密:

  1. 範本語言使用 {% ... %}{{ ... }} 包圍標記,前者用於包圍命令和流程控制陳述式,後者用於顯示變數內容。
  2. 變數的參照遵循 Python 的慣例,例如 parent.address 用於顯示 parent 物件的 address 屬性。
  3. 常用的範本語言結構包括條件判斷 (ififequal)、迴圈 (for) 和註解 (comment)。

Django 範本語言的基本結構

表格 3-4 列出了 Django 範本語言中最常用的元素。

結構描述
{% if <variable> %} ... {% else %} ... {% endif %}用於測試變數是否已定義且內容不為空。
{% for <variable> in <list> %} ... {% endfor %}用於迴圈遍歷列表中的所有專案。
{% ifequal <variable1> <variable2> %} ... {% else %} ... {% endifequal %}用於比較兩個變數並根據結果處理不同的範本區塊。
{% comment %} ... {% endcomment %}用於註解掉範本中的某些部分。

內容解密:

  1. 這些結構使得範本能夠根據變數的值動態地生成內容。
  2. 使用這些結構可以使範本更加靈活和可重用。

網頁應用程式介面

圖 3-4 展示了當我們瀏覽到其中一個預先建立的網路位址時,應用程式網頁的外觀。

內容解密:

  1. 圖 3-4 直觀地展示了應用程式的使用者介面。
  2. 使用者可以透過這個介面瀏覽、新增、修改和刪除網路位址。

在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)

內容解密:

  1. 引數解析:函式接收requestaddress兩個引數,其中address包含IP位址和網路大小。
  2. 分割IP位址和網路大小:使用split('/')方法將address分割成IP位址和網路大小。
  3. 查詢父物件:根據IP位址和網路大小查詢其父物件。
  4. 刪除記錄:呼叫delete()方法刪除指定的記錄。Django會自動處理相關子物件的刪除。
  5. 重新導向:根據父物件的存在與否,決定重新導向的URL。

新增記錄

新增記錄涉及使用者輸入,因此需要定義表單類別。

定義表單類別

from django.forms import ModelForm

class NetworkAddressAddForm(ModelForm):
    class Meta:
        model = NetworkAddress
        exclude = ('parent', )

內容解密:

  1. 表單類別定義:使用ModelForm建立一個根據NetworkAddress模型的表單。
  2. 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))

內容解密:

  1. 請求方法判斷:根據請求方法是POST還是GET進行不同的處理。
  2. POST請求處理:驗證表單資料的有效性,如果有效則儲存新記錄並重新導向。
  3. GET請求處理:顯示空白表單。
  4. 父物件指定:根據URL中的地址資訊查詢父物件並指定給新記錄。

重點回顧

  • 在Django中實作記錄的刪除和新增功能,需要定義相應的URL規則和檢視函式。
  • 刪除功能涉及查詢相關記錄並呼叫其delete()方法,Django會自動處理相關子物件的刪除。
  • 新增功能需要定義表單類別,並在檢視函式中處理表單資料的驗證和儲存。