LUCI自行定義表單處理

小小前言

前一章裏我闡述了利用LUCI的自身機制實現表單的構建及配置的讀取,如今我來講一下自行構建表單進行提交處理的方法。我的認爲,掌握了這個,纔不會被LUCI的架構所侷限。剛接觸那會,我是花了蠻長的時間才弄通了這一點,也由於在網上沒找到什麼資料,因此想把本身的經驗寫下來,也但願能幫到你們。html

具體步驟以下:git

  1. 肯定配置文件
  2. 編寫路由
  3. 創建表單
  4. 編寫處理方法
1. 肯定配置文件

這一個在前一章也有說過,你們能夠先看看個人這一篇文章:
LUCI 使用其原有機制的創建新的頁面github

這裏咱們仍然沿用以前的network配置的interface那項配置就好:vim

config interface testnets
    option ifname 'testnet'
    option type 'test'
    option ipaddr '192.168.1.1'
    option net '192.168.251.1'
2. 編寫路由

我的習慣,我喜歡先定好路由規則再往下寫。你們如果不想後面二進宮,那麼能夠先進行第3步。
話很少話,接下來咱們到luci/controller/admin/net.lua裏編寫路由:segmentfault

module luci.controller.admin.net
function index()
    entry({"admin", "testnet", "form"}, template("test/form"), translate("Form"), 12)    -- 表單加載頁面路由
   entry({"admin", "testnet", "control"}, call("form"), nil) 
end
3. 創建表單

好了,到了創建表單的時間。相信作過WEB開發的人都知道表單如何創建,其實就是一個HTML頁面。但LUCI這裏有所不一樣,用的是htm文件,但基本語法是同樣的,因此不用擔憂。
好了,咱們接下來簡單寫一下咱們的表單頁面,頁面的文件路徑是在luci/view/test/下的form.htm(由於以前路徑定義了template("test/form)這一句):api

<%+header%>
<%
    local cbi = require 'luci.model.uci'
    
    local row = cbi:get("network", "testnets")
%>
<form action="<%=url("admin", "testnet", "control")%>" method="post">
<div><label>Ifname: </label><span><input type="text" name="ifname" value="<%=row.ifname%>"/></span></div>
<div><label>Type: </label><span><input type="text" name="type" value="<%=row.type%>"/></span></div>
<div><label>ipaddr: </label><span><input type="text" name="ipaddr" value="<%=row.ipaddr%>"/></span></div>
<div><label>Net: </label><span><input type="text" name="net" value="<%=row.net%>"/></span></div>
<input type="submit" value="提交" />
</form>
<%+footer%>

在表單裏有幾點我想說一下:架構

  • 在LUCI裏的視圖層(也就是view層),是能夠嵌套LUCI的代碼的,跟PHP也能在HTML頁面嵌套代碼同樣,LUCI使用<%%>這個符號做爲LUCI代碼在.htm嵌套代碼的起始和結尾符;
  • <%+header%><%+footer%>這兩個是加載頭和尾文件的,至關於PHP的include方法。加載的文件是在視圖文件夾之下,即luci/view/header.htmluci/view/footer.htm兩個文件
  • 表單裏的action使用的luci自帶的路徑生成函數url(),寫法與控制器裏的entry()函數的第一個參數寫法一致;
  • 由於LUCI主要的功能是對配置文件進行存取,而取這一點的體現就在於view層的頁面上,因此咱們須要將其取出來就要使用LUCI的代碼。不管存取,咱們都須要用到LUCI的uci接口,也就是加載裏的luci.model.uci
  • uci接口的具體內容在它的是官方接口裏有的具體的說明,不過我的以爲它沒有實例,看得會比較吃力,但如果理解了LUCI的機制並用過一兩個接口以後就能比較好地掌握了;
  • 這裏用到的是uci的get()接口,在官方的描述是這樣的:
Uci:get (config, section, option)       
     Get a section type or an option
Parameters
    config: UCI config
    section: UCI section name
    option: UCI option (optional)
    
Return value:
    UCI value
uci:get(config, sectionType/sectionName[, optionType])接口獲取一個section或option
section如果只有類型(如: config interface)第二個參數就是 section的類型,如interface
section如果有name名(如: config interface 'testnets'),則第二個參數則寫testnets,即section的name名。
如果多有個相同類型的 section存在,獲取其中的某個 section須要獲取到單個interface的ID,這個ID的獲取如果用LUCI的傳統方式則可以經過每一行的控件或是tr的標籤id中獲取。
多個同類型的 section我的建議使用uci:foreach(config, sectionType, callbackFun)接口
Uci:foreach (config, type, callback)
    Call a function for every section of a certain type.
Parameters
    config: UCI config
    type: UCI section type
    callback: Function to be called
Return value:
    Boolean whether operation succeeded
3. 書寫處理函數

剛接觸LUCI,其實最令我感到難如下手的就是用法,本人C語言比較薄弱一些,LUCI的語法比較繞啥的,看得比較暈,研究了好些天,勉強看懂了它的基本語法,再加上LUCI官方接口文檔,纔算是找到了點感受。
[尷尬地笑]不發牢騷了,接下來編寫處理這個表單內容的代碼:函數

function form()
    local cbi = require 'luci.model.uci'
    local h = require 'luci.http'
    local dsp = require 'luci.dispatcher'
    
    local ifname = h.formvalue("ifname")
    local in_type = h.formvalue("type")
    local in_ipaddr = h.formvalue("ipaddr")
    local in_net = h.formvalue("net")
    cbi:delete("network", "testnets")
    cbi:section("network", "interface", "testnets", {
        ifname = ifname,
        type = in_type,
        ipaddr = in_ipaddr,
        net = in_net
    })
    cbi:save("network")
    cbi:commit("network")
    h.redirect(dsp.bulid_url("admin", "testnet", "form"))
end
  • cbi:section(config, sectionType, sectionName/nil, {'...'})接口是創建新的section節點,該節點的參數有四個,第一個參數是config文件的文件名,第二個參數是section的type名,第三個參數是section的name名(如果沒有,可爲空),第四個參數是具體的配置項內容
  • 也許是我沒找到替代方法的緣由,我對於接口的修改都是先刪掉再新建。所以,須要調用先cbi:delete(config, section[, option])接口。該接口與前面獲取section的uci:get()接口的使用方法一致。
  • 在Linux使用過uci命令的童鞋應該會知道:section/option進行操做以後都須要commit纔是完成了操做。而LUCI裏也提供了uci:commit(config)接口,在LUCI裏須要先保存再提交,即應該先調用uci:save(config)接口,再調用commit接口。
Uci:delete (config, section, option)
    Deletes a section or an option.
Parameters
    config: UCI config
    section: UCI section name
    option: UCI option (optional)
Return value:
    Boolean whether operation succeeded
Uci:section (config, type, name, values)
    Create a new section and initialize it with data.
Parameters
    config: UCI config
    type: UCI section type
    name: UCI section name (optional)
    values: Table of key - value pairs to initialize the section with
Return value:
    Name of created section
Cursor:save (config)
    Saves changes made to a config to make them committable.
Parameters
    config: UCI config
Return value:
    Boolean whether operation succeeded
Cursor:commit (config)
    Commit saved changes.
Parameters
    config: UCI config
Return value:
    Boolean whether operation succeeded

至此,咱們本身進行section的存取操做就完成了。加上上一章,好像內容說得比較囉嗦,由於寫技術文寫得很少,還請見諒;同時也是由於我以爲這些經驗都是挺重要的,因此寫了下來。LUCI我接觸的時間並不長,有說明不清或者錯誤地方,歡迎你們不吝指出~
但願本文能幫到你們,也但願能於你們多多交流!post

相關文章
相關標籤/搜索