一、认识Luci的整体结构

2023-11-08

Luci采用的是MVC的Web框架,即Model、View、Controller

/usr/lib/lua/luci/controller/   --控制层 
/usr/lib/lua/luci/view/ 		--视图层
/usr/lib/lua/luci/model/cbi/	--模型层

一、控制层Controller

控制层中的文件语法精简结构如下,主要为两个部分:模块声明和路由定义。

module("luci.controller.admin.network", package.seeall)
function index()
    --定义方式1
    entry({"admin", "network"}, firstchild(), _("Network") , 1)
    --定义方式2
    local page;
    page  = node("admin", "network", "vlan")
    page.target = cbi("admin_network/vlan")
    page.title  = _("Switch")
    page.order  = 20
    
    entry({"admin",'network',"tabs"},firstchild(),"Tabs",30)
    --添加三级菜单
    entry({"admin","network","tabs","tab1"},call("fun"),'Tab1',1)
    entry({"admin","network","tabs","tab4"},template("tab4_tpl"),"Tab4",4)
end
local function fun ()
    --执行fun方法
end

1、模块声明:

文件定义时需要声明其模块名称,按照其路径定义即可,比如该文件位于 /luci/controller/admin/network.lua

module(“luci.controller.admin.network”, package.seeall)

2、路由定义:

上面代码中我们可以看到使用了两种定义路由的方式,一种是直接使用entry方法来定义一个路由,并传入以下4个参数。第二种方式是使用node方法直接定义路由的路径,然后分开指定其他target,title等属性。entry方法内部也是使用node方法,所以两种方式等效。

entry(path, target, title=nil, order=nil)
  • path : 规定了此路由的访问路径,参数是一个字符串数组,比如 {“admin”, “test”, “test_view”} 这样的参数,在页面访问的时候,路径为 /admin/test/test_view ,"test" 是一级菜单。"test_view" 为二级菜单。如果使用node方法直接创建,则需要散列传参,不需要传入table。

  • target :规定访问此路径时,Luci框架执行的调用目标,根据调用目标的不同,LuCI
    也有不同的调度行为。所有的target类型,在源码文件 dispatcher.lua中可以找到。target主要使用的有aliasfirstchildcalltemplatecbiformarcombine

  • title:定义该节点在菜单上显示的名称,非必填项,如果使用了国际化配置,可以使用_(“Router”)这样的表示方式,在中文环境下显示路由,在英文环境下显示Router。如果不填title,则不会在菜单栏上面显示。但是可以通过url进行访问。

  • order:该节点在同级节点下的显示顺序。非必填项,从上至下,从左至右数值越小显示越靠前。 属性

  • target主要有如下种类:

    • firstchild() :自动指向该节点的第一个子节点(order最小的那个节点)
    • call(func_name):调用该文件下的指定函数,比如 call(“test_function”),则会在访问当前路径时,调用该文件下的test_function函数。在这些函数中,我们也可以处理一些数据。
    • template(tpl_name):根据给定的HTM模板名称访问指定的HTML页面,路径对应luci/view下面的文件。比如template(“admin_system/hello”),对应luci/view/admin_system/hello.htm 文件。
    • cbi(model,config):根据给定的model文件名,渲染一个CBI模型。路径对应luci/model/cbi下面的文件。同时可以传入一些config信息,比如 {nofooter:不显示cbi_footer,noheader:不显示cbi_header} 等等。其他用法可以在源码 dispatcher.lua 的 _cbi方法中进行查看。
    • form(model) : 与cbi()类似,不过渲染的是一个表单CBI模型。
    • arcombine(trg1,trg2):当需要访问同一个路由,而这个路由在有参和无参时的调用目标需要不一致的时候,可以使用arcombine把两个target进行组合起来(比如某个列表和其详情页分开时)。当有参数时调用trg2,无参时调用trg1.
    • alias(Path):重定向到另外一个节点上。
-- 访问/admin/test 时, 重定向到 /admin/test/test_view
entry({"admin", "test"}, alias("admin", "test", "test_view"), "重定向", 1)

节点属性:使用变量接收node方法或者entry方法返回的节点后,可以选择添加的属性。

  • i18n :定义了在请求页面时应自动加载哪个翻译文件

  • dependent :保护插件在父节点丢失时从上下文中调用

  • leaf :停止在此节点处解析请求,并且在调度树中不再进一步

  • sysauth :要求用户使用指定的帐户进行身份验证

  • sysauth_authenticator :验证时手动指定验证方法

  • setgroup :设置当前进程的组ID

  • setuser:设置当前进程的用户ID

上面的属性的使用,在dispatcher.lua文件中的dispatch方法中有体现。

二、视图层 View

在controller中提到,target 可以使用 template 可以指定对应的htm文件作为界面显示。同样,在使用cbi,form等方法指定target时,最后也会根据htm文件来渲染界面。具体流程在后续解释。这个htm文件所属范畴就是View中,浏览器界面主要由两种途径产生,使用CBI模型进行生成,或者是自定义htm显示。CBI模型是使用Luci预定义的一些CBI组件来生成常用的表单。如果需要制作一些CBI文件满足不了的页面,可以自己定义htm文件来满足需求。
htm文件中通常由三大部分构成:Lua代码、HTML代码、JavaScript代码。

--lua代码
<%
    local sys = require "luci.sys"
-%>
--JavaScript代码
<script>
    function(){
        console.log('This is JavaScript Code')    
    }
</script>
--HTML代码
<%+header%>
    <h1><%: HelloWorld %></h1>
    <h1><%= sys.hostname() %></h1>
<%+footer%>

语法解释
在htm文件中,可以在HTML代码和JavaScript代码中插入lua代码,使用下面的语法格式标志代码为Lua代码。可以嵌套进行使用。具体实例在后续CBI模型渲染过程的解析中。
1、 包含Lua代码块:

<% code %>
<%- code -%>

2、 输出变量和函数值:

<% write(value) %>
<%=value%>

3、 引用另一个模板:

<% include(templatesName) %>
<%+ templatesName %>

4、 翻译转换:

<%= translate(“Text to translate”) %>
<%:Text to translate%>

5、 注释:

<%# comment %>

三、模型层 Model

controller中提到。target 使用 cbi可以根据给出的文件创建一个CBI模型进行界面渲染。官方的说,CBI模型是Lua文件描述UCI配置文件的结构和由此参生的HTML表单来评估CBI解析器。通俗的说就是CBI模型通常由LuCI预定义的一些CBI控件组成,不同的CBI控件根据其对应的模板生成页面上可见的表单元素。这些控件可以执行大部分的UCI配置的获取或者设置的处理工作。我们也可以覆盖其本来的行为来达到我们满足项目需求的目的。

在我们定义的CBI文件中,与UCI的配置息息相关,UCI配置暂时可以理解为系统的各个应用程序的配置的统一接口。后面再详细介绍UCI。CBI模型文件定义在 /model/cbi/ 目录下

简单介绍一下CBI模型中的语法结构。后面对CBI控件进行详细介绍。以下面的代码为例。

m = Map("sn_file", translate("产品序列号")) 
d = m:section(TypedSection, "gateway_sn",nil,nil) 
a = d:option(Value, "sn", translate("序列号"));
return m
-------------------------------
1、表示生成一个map对象,对/etc/config/sn_file 文件进行映射
2、添加TypedSection 对type为"gateway_sn"的配置进行映射
3、添加一个Value输入框,对"gateway_sn"下的选项"sn"进行映射
    对应的 /etc/config/sn_file 文件的UCI配置为
    config gateway_sn
        option sn "sn"

所有CBI luci.cbi.Map类型的模型文件必须返回一个map对象。

m = Map(config, title,description)
-- 第一个参数,代表 cbi 基于某个配置文件 config 建立Map, 
-- 比如'system'对应配置文件 /etc/config/system
-- 第二个参数, 映射页面的标题,第三个参数, 描述信息

d = m:section(sectionClass,...)
--section是Map实例上的一个方法,作用是
--为map对象添加一个sectionClass类。
--section方法接收的参数只会使用到第一个,剩余的参数
--全部传递给sectionClass类使用。
--常用的sectionClass类有TypedSection NameSection两种
--比如 m:section(TypedSection, type, title, description)
--表示为Map对象增添一个TypedSection类,
-- type, title, description 参数会传递给 TypedSection
-- type 表示对 /etc/config/system 下类型为 type 的配置进行映射。

a = d:option(optionClass,...)
-- option是TypedSection实例的一个方法,作用是
-- 添加一个选项,对TypedSection所定义的某个type下的option进行映射。
-- 第一个参数为optionClass,比如Value、ListValue等等,
-- 同样,传递给option方法的参数都会传递到optionClass中
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一、认识Luci的整体结构 的相关文章

  • 如何将 Lua 嵌入到 Python 3.x 中?

    是否可以将 Lua 嵌入到 Python 3 x 中 如果是这样 我如何在我的 Python 程序中运行和执行 Lua 脚本 语言之间的交互有多好 例如 Lua 是否可以访问 Python 的所有变量和类以及 Python 是否可以访问 L
  • 迭代包括空行在内的行

    给定一个带有一些空行的多行字符串 我如何在Lua中迭代行包括空行 local s foo nbar n njim for line in magiclines s do print line and blank or line end gt
  • 如何使用循环将字符串连接成一个?

    有人可以帮我解决字符串连接问题吗 我从寄存器读取数据 它的函数 utf regAddr length 我得到带有十进制数字的表格 然后将其转换为十六进制并循环字符串 我需要将这些字符串连接成一个 Lua中没有像 这样的操作符 functio
  • LuaJit FFI 从 C 函数返回字符串到 Lua?

    假设我有这个 C 函数 declspec dllexport const char GetStr static char buff 32 Fill the buffer with some string here return buff 这
  • Lua中如何获取目录列表

    我需要 LUA 中的目录列表 假设我的目录路径为 C Program Files 我需要该特定路径中所有文件夹的列表以及如何搜索该列表中的任何特定文件夹 Example 需要路径 C Program Files 中所有文件夹的列表 以下是上
  • Lua 中的内联条件(a == b ? "yes" : "no")?

    无论如何 Lua 中可以使用内联条件吗 Such as print blah a true blah nahblah Sure print blah a and blah or nahblah
  • C 的哪些部分最可移植?

    我最近读到了 Lua 联合创始人 Luiz H de Figueredo 和 Roberto Ierusalimschy 的采访 他们讨论了 Lua 的设计和实现 至少可以说这是非常有趣的 然而 讨论的一部分让我想起了一些事情 Robert
  • lua http套接字超时

    LuaSocket HTTP 模块文档说可以在 HTTP 连接上设置超时 可以设置以下常量来控制 HTTP 模块的默认行为 PORT 用于连接的默认端口 PROXY 用于连接的默认代理 TIMEOUT 设置所有I O操作的超时时间 USER
  • 如何在aerospike中获取ttl为-1的记录集?

    我在aerospike中有很多记录 我想获取ttl为 1的记录 请提供解决方案 只是为了澄清 设置TTL 为 1 https github com aerospike aerospike client go blob master docs
  • Lua userdata:无法同时进行数组访问和方法

    我遇到了这个人的问题 Lua userdata数组访问及方法 https stackoverflow com questions 26970316 lua userdata array access and methods 其中 当我设置用
  • 如何在Conky中实现一个基本的Lua功能?

    我正在尝试向我的 Conky 添加一个函数 该函数打印字符串的长度以用于调试目的 代码位于名为的文件内test lua 非常简单 function test word return string len word end 我这样加载它 在我
  • 关闭 Löve2D 中的抗锯齿功能

    我在用着L ve2D http love2d org用于编写一个小游戏 L ve2D 是 Lua 的开源游戏引擎 我遇到的问题是 当您在非整数位置绘制精灵时 某些抗锯齿过滤器会自动应用于精灵 love graphics draw sprit
  • gsub 的转义字符串

    我读了一个文件 local logfile io open log txt r data logfile read a print data output n w r 1 2 n t x re S 是的 日志文件看起来很糟糕 因为它充满了各
  • 推送 Lua 表

    我已经创建了一个Lua表C 但我不知道如何将该表推入堆栈顶部 以便我可以将其传递给 Lua 函数 有谁知道如何做到这一点 这是我当前的代码 lua createtable state libraries size 0 int table i
  • Lua 上的 For 循环

    我的作业是如何执行 for 循环 我已经从数字上弄清楚了 但无法从名称上弄清楚 我想创建一个 for 循环来运行名称列表 以下是我到目前为止所拥有的 names John Joe Steve for names 1 3 do print n
  • SHA2 512 的改编给出了不正确的结果

    我正在尝试调整 SecureHashAlgorithm 的纯 Lua 实现here http lua users org wiki SecureHashAlgorithm对于 SHA2 512 而不是 SHA2 256 当我尝试使用改编时
  • Lua 的标准(或最好支持的)大数(任意精度)库是什么?

    我正在处理大量无法四舍五入的数字 使用 Lua 的标准数学库 似乎没有方便的方法来保持精度超过某些内部限制 我还看到有几个库可以加载以处理大数字 http oss digirati com br luabignum http oss dig
  • 在 Lua 中只归档一次

    我想知道是否有一种方法可以只执行一次 lua 文件 并且后续尝试执行该 lua 文件将导致无操作 我已经考虑过做一些类似于 C header 的 if else endif 技巧的事情 我想知道是否有一个标准方法来实现这一点 James w
  • 在 lua 中加载 C++ 模块时出现“尝试索引字符串值”错误

    我正在尝试使用 lua 用 C 编写的函数 下面给出的是cpp文件 extern C include lua h include lauxlib h include lualib h static int add 5 lua State L
  • 克隆一个lua状态

    最近 我在使用C 和Lua进行开发时遇到了很多困难 我的情况是 由于某种原因 我的 C 程序中可能有数千个 Lua 状态 但这些状态在初始化后应该是相同的 当然 我可以为每个状态执行 luaL loadlibs 和 lua loadfile

随机推荐

  • halcon像素统计_Halcon(八)亚像素轮廓XLD

    fast threshold Image Region 0 120 7 boundary Region RegionBorder inner dilation circle RegionClipped RegionDilation 2 5
  • Cox-Box变换

    在 回归分析的基本假设 中提到了回归分析中的基本假设 这里的Box Cox变换方法能够解决回归模型中的误差项不服从高斯分布的违例问题 通常这种违例情况出现在 误差 epsilon与预测变量相关的时候 会影响模型结果的精确度 简单的方法就是通
  • 了解redis的单线程模型工作原理?一篇文章就够了

    1 首先redis是单线程的 为什么redis会是单线程的呢 从redis的性能上进行考虑 单线程避免了上下文频繁切换问题 效率高 从redis的内部结构设计原理进行考虑 redis是基于Reactor模式开发了自己的网络事件处理器 这个处
  • 输入一个十进制数,输出其二进制,八进制,十六进制

    a int input 请输入一个十进制整数 print 其对应二进制为 b n八进制为 o n十六进制为 x format a a a
  • Java并发编程面试题——JUC专题

    一 AQS高频问题 1 1 AQS是什么 AQS是JUC下大量工具的基础类 很多工具都基于AQS实现的 比如lock锁 CountDownLatch Semaphore 线程池等等都用到了AQS AQS中有一个核心属性state 还有一个双
  • 基于react+and Design实现下拉框,支持自由输入

    基于react and Design实现下拉框 支持自由输入 以下是基于select的改造方案 使用AutoComplete组件更简单方便一些 AutoComplete这组件的实现方式请移步 基于react and Design实现下拉框
  • mysql 数据库授权(给某个用户授权某个数据库)

    mysql 数据库授权 给某个用户授权某个数据库 版权 1 小唐唐 https blog csdn net qq 38390092 article details 90340804 2 季枫 https www cnblogs com ji
  • PCB设计中常用的尺寸标注

    PCB设计中常用的尺寸标注 原创 凡亿教育 凡亿PCB 凡亿PCB 为了使设计者或生产者更方便地知晓PCB尺寸及相关信息 在设计的时候通常考虑到给设计好的PCB添加尺寸标注 尺寸标注方式分为线性 圆弧半径 角度等形式 下面对最常用的线性标注
  • canteen php,PHP脚本任务优化思路或改进方案?

    脚本部分 date default timezone set PRC require once canteen MySQL php mysql MySQL getInstance localhost root 123456 canteens
  • Oracle 修改字段非空属性问题

    背景 最近因为项目要做国际推广 然后在国外使用环境中有一个我们国内系统必填的字段是不需要的 导致一些问题所以需要修改数据库中对应字段的非空属性为允许为空 因为sql水平实在渣渣 只能网上搜索结果 找到一堆答案 但是没一个能成功执行的 不知是
  • ViewModelScope 避免内存泄漏的原理

    避免的是什么 避免的是协程的内存泄漏 如何避免 总体逻辑 通过 lifecycle 监听 Activity 的生命周期 在 Activity 销毁时对协程进行 cancel 监听状态变化 下图代码是注册监听的地方 可以看到在 Activit
  • 2014第五届蓝桥杯JavaB组决赛(国赛)试题汇总及试题详解

    蓝桥杯历年省赛真题汇总及题目详解 蓝桥杯历年决赛试题汇总及试题详解 目录 第一题 国王的遗产 第二题 六角幻方 第三题 格子放鸡蛋 第四题 排列序数 第五题 幂一矩阵 第六题 供水设施 第一题 国王的遗产 题目描述 X国是个小国 国王K有6
  • oracle数据库级别优化分析工具介绍

    author skatetime 2010 03 04 oracle数据库级别优化分析工具介绍 当我们对数据库优化诊断时 需要收集相应的信息以供参考 从个人的使用经验来说 这种统计数据分为两大类 一类是数据库级别的统计信息二类是os级别的统
  • 常见iPhone恢复固件(DFU模式)的三种方法

    可能你听说iPhone的DFU模式 DFU的全称是Development Firmware Upgrade 实际意思就是iPhone固件的强制升降级模式 例如 在你降级iPhone固件的时候 如果出现过错误 1 或者错误 6 那么在你恢复或
  • 如何使用ESP32相机模组实现视频流和人脸识别

    人证识别系统有许多种方式 比如使用签名 指纹 语音 面部识别等来识别人员 但是只有人脸识别系统可以检测和识别机场 零售店和火车站等公共场所中的人员 人脸识别系统不仅可以用于安全目的以识别公共场所中的人员 还可以用于办公室和学校中的考勤记录
  • ESP8266使用详解(AT,LUA,SDK)

    https www cnblogs com yangfengwu p 10100152 html 8266综合开发教程 AT LUA SDK 推荐 https www cnblogs com yangfengwu category 1187
  • android 自定义时钟控件

    效果截图 自定义时钟组件源代码 package com sky dreaming analogic clock view import android content Context import android content Inten
  • Python 中的 sequence 类型

    在查看Python 内置的帮助文档的时候 我发现其对函数的定义def是如下形式的 duplicated subset Hashable Sequence Hashable None None keep Literal first Liter
  • 基于栈的算术表达式求值算法

    基于栈的算术表达式求值算法 在计算机科学中 算术表达式求值是一个非常重要且常见的问题 通常 我们使用中缀表示法来编写算术表达式 而计算机则使用后缀表示法 也称为逆波兰表示法 来进行求值 本文将介绍一种基于栈的算法来解决这个问题 栈数据结构
  • 一、认识Luci的整体结构

    Luci采用的是MVC的Web框架 即Model View Controller usr lib lua luci controller 控制层 usr lib lua luci view 视图层 usr lib lua luci mode