docs: add documentation for gluon-web
This commit is contained in:
parent
31d3f08f25
commit
22746a2a0d
117
docs/dev/web/controller.rst
Normal file
117
docs/dev/web/controller.rst
Normal file
@ -0,0 +1,117 @@
|
||||
Controllers
|
||||
===========
|
||||
|
||||
Controllers live in ``/lib/gluon/web/controller``. They define which pages ("routes")
|
||||
exist under the ``/cgi-bin/gluon`` path, and what code is run when these pages are requested.
|
||||
|
||||
Controller scripts mostly consist of calls of the `entry` function, which each define
|
||||
one route:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
entry({"admin"}, alias("admin", "info"), _("Advanced settings"), 10)
|
||||
entry({"admin", "info"}, template("admin/info"), _("Information"), 1)
|
||||
|
||||
The entry function expects 4 arguments:
|
||||
|
||||
- `path`: Components of the path to define a route for.
|
||||
|
||||
The above example defines routes for the paths ``admin`` and ``admin/info``.
|
||||
|
||||
- `target`: Dispatcher for the route. See the following section for details.
|
||||
- `title`: Page title (also used in navigation). The underscore function is used
|
||||
|
||||
- `order`: Sort index in navigation (defaults to 100)
|
||||
|
||||
Navigation indexes are automatically generated for each path level. Pages can be
|
||||
hidden from the navigation by setting the `hidden` property of the node object
|
||||
returned by `entry`:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
entry({"hidden"}, alias("foo"), _("I'm hidden!")).hidden = true
|
||||
|
||||
|
||||
Dispatchers
|
||||
-----------
|
||||
|
||||
- *alias* (*path*, ...): Redirects to a different page. The path components are
|
||||
passed as individual arguments.
|
||||
- *call* (*func*, ...): Runs a Lua function for custom request handling. The given
|
||||
function is called with the HTTP object and the template renderer as first
|
||||
two arguments, followed by all additional arguments passed to `call`.
|
||||
- *template* (*view*): Renders the given view. See :doc:`view`.
|
||||
- *model* (*name*): Displays and evaluates a form as defined by the given model. See the
|
||||
:doc:`model` page for an explanation of gluon-web models.
|
||||
|
||||
|
||||
.. _web-controller-http:
|
||||
|
||||
The HTTP object
|
||||
---------------
|
||||
|
||||
The HTTP object provides information about the HTTP requests and allows to add
|
||||
data to the reply. Using it directly is rarely necessary when gluon-web
|
||||
models and views are used.
|
||||
|
||||
Useful functions:
|
||||
|
||||
- *getenv* (*key*): Returns a value from the CGI environment passed by the webserver.
|
||||
- *formvalue* (*key*): Returns a value passed in a query string or in the content
|
||||
of a POST request. If multiple values with the same name have been passed, only
|
||||
the first is returned.
|
||||
- *formvaluetable* (*key*): Similar to *formvalue*, but returns a table of all
|
||||
values for the given key.
|
||||
- *status* (*code*, *message*): Writes the HTTP status to the reply. Has no effect
|
||||
if a status has already been sent or non-header data has been written.
|
||||
- *header* (*key*, *value*): Adds an HTTP header to the reply to be sent to to
|
||||
the client. Has no effect when non-header data has already been written.
|
||||
- *prepare_content* (*mime*): Sets the *Content-Type* header to the given MIME
|
||||
type, potentially setting additional headers or modifying the MIME type to
|
||||
accommodate browser quirks
|
||||
- *write* (*data*, ...): Sends the given data to the client. If headers have not
|
||||
been sent, it will be done before the data is written.
|
||||
|
||||
|
||||
HTTP functions are called in method syntax, for example:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
http:write('Output!')
|
||||
|
||||
|
||||
.. _web-controller-template-renderer:
|
||||
|
||||
The template renderer
|
||||
---------------------
|
||||
|
||||
The template renderer allows to render templates (views). The most useful functions
|
||||
are:
|
||||
|
||||
- *render* (*view*, *scope*): Renders the given view, optionally passing a table
|
||||
with additional variables to make available in the template.
|
||||
- *render_string* (*str*, *scope*): Same as *render*, but the template is passed
|
||||
directly instead of being loaded from the view directory.
|
||||
|
||||
The renderer functions are called in property syntax, for example:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
renderer.render('layout')
|
||||
|
||||
|
||||
Differences from LuCI
|
||||
---------------------
|
||||
|
||||
- Controllers must not use the *module* function to define a Lua module (*gluon-web*
|
||||
will set up a proper environment for each controller itself)
|
||||
- Entries are defined at top level, not inside an *index* function
|
||||
- The *alias* dispatcher triggers an HTTP redirect instead of directly running
|
||||
the dispatcher of the aliased route.
|
||||
- The *call* dispatcher is passed a function instead of a string with a function
|
||||
name.
|
||||
- The *cbi* dispatcher of LuCI has been renamed to *model*.
|
||||
- The HTTP POST handler support the multipart/form-data encoding only, so
|
||||
``enctype="multipart/form-data"`` must be included in all *<form>* HTML
|
||||
elements.
|
||||
- Other dispatchers like *form* are not provided.
|
148
docs/dev/web/model.rst
Normal file
148
docs/dev/web/model.rst
Normal file
@ -0,0 +1,148 @@
|
||||
Models
|
||||
======
|
||||
|
||||
Models are defined in ``/lib/gluon/web/model``. Each model defines one or more
|
||||
forms to display on a page, and how the submitted form data is handled.
|
||||
|
||||
Let's start with an example:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
local f = Form(translate('Hostname'))
|
||||
|
||||
local s = f:section(Section)
|
||||
|
||||
local o = s:option(Value, 'hostname', translate('Hostname'))
|
||||
o.default = uci:get_first('system', 'system', 'hostname')
|
||||
function o:write(data)
|
||||
uci:set('system', uci:get_first('system', 'system'), 'hostname', data)
|
||||
uci:commit('system')
|
||||
end
|
||||
|
||||
return f
|
||||
|
||||
The toplevel element of a model is always a *Form*, but it is also possible for
|
||||
a model to return multiple forms, which are displayed one below the other.
|
||||
|
||||
A *Form* has one or more *Sections*, and each *Section* has different types
|
||||
of options.
|
||||
|
||||
All of these elements have an *id*, which is used to identify them in the HTML
|
||||
form and handlers. If no ID is given, numerical IDs will be assigned automatically,
|
||||
but using explicitly named elements is often advisable (and it is required if a
|
||||
form does not always include the same elements, i.e., some forms, sections or
|
||||
options are added conditionally). IDs are hierarchical, so in the above example,
|
||||
the *Value* would get the ID ``1.1.hostname`` (value *hostname* in first section
|
||||
of first form).
|
||||
|
||||
Classes and methods
|
||||
-------------------
|
||||
|
||||
- *Form* (*title*, *description*, *id*)
|
||||
|
||||
- *Form:section* (*type*, *title*, *description*, *id*)
|
||||
|
||||
Creates a new section of the given type (usually *Section*).
|
||||
|
||||
- *Form:write* ()
|
||||
|
||||
Is called after the form has beed submitted (but only if the data is valid). It
|
||||
is called last (after all options' *write* methods) and is usually used
|
||||
to commit changed UCI packages.
|
||||
|
||||
The default implementation of *write* doesn't to anything, but it can be
|
||||
overridden.
|
||||
|
||||
- *Section* (usually instanciated through *Form:section*)
|
||||
|
||||
- *Section:option* (*type*, *id*, *title*, *description*)
|
||||
|
||||
Creates a new option of the given type. Option types:
|
||||
|
||||
- *Value*: simple text entry
|
||||
- *TextValue*: multiline text field
|
||||
- *ListValue*: radio buttons or dropdown selection
|
||||
- *DynamicList*: variable number of text entry fields
|
||||
- *Flag*: checkbox
|
||||
|
||||
Most option types share the same properties and methods:
|
||||
|
||||
- *default*: default value
|
||||
- *optional*: value may be empty
|
||||
- *datatype*: one of the types described in :ref:`web-model-datatypes`
|
||||
|
||||
By default (when *datatype* is *nil*), all values are accepted.
|
||||
|
||||
- *state*: has one of the values *FORM_NODATA*, *FORM_VALID* and *FORM_INVALID*
|
||||
when read in a form handler
|
||||
|
||||
An option that has not been submitted because of its dependencies will have
|
||||
the state *FORM_NODATA*, *FORM_INVALID* if the submitted value is not valid
|
||||
according to the set *datatype*, and *FORM_VALID* otherwise.
|
||||
|
||||
- *data*: can be read in form handlers to get the submitted value
|
||||
|
||||
- *depends* (*self*, *option*, *value*): adds a dependency on another option
|
||||
|
||||
The option will only be shown when the passed option has the given value. This
|
||||
is mainly useful when the other value is a *Flag* or *ListValue*.
|
||||
|
||||
- *depends* (*self*, *deps*): adds a dependency on multiple other options
|
||||
|
||||
*deps* must be a table with options as keys and values as values. The option
|
||||
will only be shown when all passed options have the corresponding values.
|
||||
|
||||
Multiple alternative dependencies can be added by calling *depends* repeatedly.
|
||||
|
||||
- *value* (*self*, *value*, *text*): adds a choice to a *ListValue*
|
||||
|
||||
- *write* (*self*, *data*): is called with the submitted value when all form data is valid.
|
||||
|
||||
Does not do anything by default, but can be overridden.
|
||||
|
||||
The *default* value, the *value* argument to *depends* and the output *data* always have
|
||||
the same type, which is usually a string (or *nil* for optional values). Exceptions
|
||||
are:
|
||||
|
||||
- *Flag* uses boolean values
|
||||
- *DynamicList* uses a table of strings
|
||||
|
||||
Despite its name, the *datatype* setting does not affect the returned value type,
|
||||
but only defines a validator the check the submitted value with.
|
||||
|
||||
For a more complete example that actually makes use of most of these features,
|
||||
have a look at the model of the *gluon-web-network* package.
|
||||
|
||||
.. _web-model-datatypes:
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
- *integer*: an integral number
|
||||
- *uinteger*: an integral number greater than or equal to zero
|
||||
- *float*: a number
|
||||
- *ufloat*: a number greater than or equal to zero
|
||||
- *ipaddr*: an IPv4 or IPv6 address
|
||||
- *ip4addr*: an IPv4 address
|
||||
- *ip6addr*: an IPv6 address
|
||||
- *wpakey*: a string usable as a WPA key (either between 8 and 63 characters, or 64 hex digits)
|
||||
- *range* (*min*, *max*): a number in the given range (inclusive)
|
||||
- *min* (*min*): a number greater than or equal to the given minimum
|
||||
- *max* (*max*): a number less than or equal to the given maximum
|
||||
- *irange* (*min*, *max*): an integral number in the given range (inclusive)
|
||||
- *imin* (*min*): an integral number greater than or equal to the given minimum
|
||||
- *imax* (*max*): an integral number less than or equal to the given maximum
|
||||
- *minlength* (*min*): a string with the given minimum length
|
||||
- *maxlength* (*max*): a string with the given maximum length
|
||||
|
||||
Differences from LuCI
|
||||
---------------------
|
||||
|
||||
- LuCI's *SimpleForm* and *SimpleSection* are called *Form* and *Section*, respectively
|
||||
- Is it not possible to add options to a *Form* directly, a *Section* must always
|
||||
be created explicitly
|
||||
- Many of LuCI's CBI classes have been removed, most importantly the *Map*
|
||||
- The *rmempty* option attribute does not exist, use *optional* instead
|
||||
- Only the described data types are supported
|
||||
- Form handlers work completely differently (in particular, a *Form*'s *handle*
|
||||
method should usually not be overridden in *gluon-web*)
|
55
docs/dev/web/view.rst
Normal file
55
docs/dev/web/view.rst
Normal file
@ -0,0 +1,55 @@
|
||||
Views
|
||||
=====
|
||||
|
||||
The template parser reads views from ``/lib/gluon/web/view``. Writing own view
|
||||
should be avoided in favour of using :doc:`model` with their predefined views.
|
||||
|
||||
Views are partial HTML pages, with additional template tags that allow
|
||||
to embed Lua code and translation strings. The following tags are defined:
|
||||
|
||||
- ``<%`` ... ``%>`` evaluates the enclosed Lua expression.
|
||||
- ``<%=`` ... ``%>`` evaluates the enclosed Lua expression and prints its value.
|
||||
- ``<%+`` ... ``%>`` includes another template.
|
||||
- ``<%:`` ... ``%>`` translates the enclosed string using the loaded i18n catalog.
|
||||
- ``<%_`` ... ``%>`` translates the enclosed string *without escaping HTML entities*
|
||||
in the translation. This only makes sense when the i18n catalog contains HTML code.
|
||||
- ``<%#`` ... ``%>`` is a comment.
|
||||
|
||||
All of these also come in the whitespace-stripping variants ``<%-`` and ``-%>`` that
|
||||
remove all whitespace before or after the tag.
|
||||
|
||||
Complex combinations of HTML and Lua code are possible, for example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
<div>
|
||||
<% if foo then %>
|
||||
Content
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
||||
Variables and functions
|
||||
-----------------------
|
||||
|
||||
Many call sites define additional variables (for example, model templates can
|
||||
access the model as *self* and an unique element ID as *id*), but the following
|
||||
variables and functions should always be available for the embedded Lua code:
|
||||
|
||||
- *renderer*: :ref:`web-controller-template-renderer`
|
||||
- *http*: :ref:`web-controller-http`
|
||||
- *request*: Table containing the path components of the current page
|
||||
- *url* (*path*): returns the URL for the given path, which is passed as a table of path components.
|
||||
- *attr* (*key*, *value*): Returns a string of the form ``key="value"``
|
||||
(with a leading space character before the key).
|
||||
|
||||
*value* is converted to a string (tables are serialized as JSON) and HTML entities
|
||||
are escaped. Returns an empty string when *value* is *nil* or *false*.
|
||||
- *include* (*template*): Includes another template.
|
||||
- *node* (*path*, ...): Returns the controller node for the given page (passed as
|
||||
one argument per path component).
|
||||
|
||||
Use ``node(unpack(request))`` to get the node for the current page.
|
||||
- *pcdata* (*str*): Escapes HTML entities in the passed string.
|
||||
- *urlencode* (*str*): Escapes the passed string for use in an URL.
|
||||
- *translate* and *translatef*: see :doc:`i18n`
|
@ -41,11 +41,21 @@ Developer Documentation
|
||||
dev/basics
|
||||
dev/hardware
|
||||
dev/upgrade
|
||||
dev/configmode
|
||||
dev/wan
|
||||
dev/i18n
|
||||
dev/mac_addresses
|
||||
|
||||
gluon-web Reference
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
dev/web/controller
|
||||
dev/web/model
|
||||
dev/web/view
|
||||
dev/web/i18n
|
||||
dev/web/config-mode
|
||||
|
||||
Packages
|
||||
--------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user