Introduction to layouts¶
A layout is a description of how to visually arrange the fields and other data elements in an entry form or a table.
Layouts are one of Lino's important features, which it adds to the Django framework. They provide a way to design forms using the Python language and independently of the chosen front end.
Code example in this document are taken from A Local Exchange Trade System.
The columns of a table¶
The simplest occurrence of layouts is the column_names
attribute of a table,
used to define which fields should be displayed as the columns of that
table.
class Products(dd.Table):
...
column_names = 'id name providers customers'
...
Result:

The layout of a detail window¶
Another frequent usage of layouts is the detail window, i.e. the window used to display one table row at a time.
You define a detail window by setting the detail_layout
attribute of a table. For
example:
class Members(dd.Table):
...
detail_layout = """
id name place email
OffersByMember DemandsByMember
"""
Result:

Note that the names id
, name
, place
and email
in the
above example represent single-line entry fields while
OffersByMember
and DemandsByMember
refer to multi-line
panels containing a grid.
The insert window¶
Insert windows are similar to detail windows, but they are used on rows that do not yet exist. The most visible difference is their default size: while detail windows usually take the full screen, insert windows usually are modular pop-up windows.
You define an insert window by setting the insert_layout
attribute of a table. For
example:
class Members(dd.Table):
...
insert_layout = """
name place
email
"""
Result:

Where layouts are being used¶
Until now we have seen that the following attributes of your tables contain layouts:
column_names
contains an instance ofColumnsLayout
detail_layout
contains an instance ofDetailLayout
insert_layout
contains an instance ofInsertLayout
There are two other places where Lino uses layouts:
The parameter panel of a table, specified as the
params_layout
attribute and containing an instance ofParamsLayout
. See Introduction to actor parameters.The optional action dialog of a custom action, specified as the
params_layout
attribute of an action and containing an instance ofActionParamsLayout
). See Introduction to action parameters.
Data elements¶
The data elements of a normal layout (ColumnsLayout
,
DetailLayout
or InsertLayout
), can be:
database fields
virtual fields
panels (see below)
ParamsLayout
are special but similar: their data elements
refer to the actor parameters.
And the data elements of an ActionParamsLayout
refer to the action parameters.
The template string¶
For simple layouts it is enough to specify them just as a string
template, as in the examples above. Lino will automatically convert
such string templates into instances of ColumnsLayout
,
DetailLayout
, InsertLayout
, ParamsLayout
or
ActionParamsLayout
.
A layout template is a string containing words, where each word is the name of a data element.
Panels¶
A Layout consists of panels.
Every layout has at least one panel whose name is main
.
When a detail_layout
is
a string, then Lino replaces this by a DetailLayout
instance
whose main panel is that string.
Writing layouts as classes¶
In more complex situations it may be preferrable or even necessary to define your own layout class.
You do this by subclassing DetaiLayout
. For example:
class PartnerDetail(dd.DetailLayout):
main = """
id name
description contact
"""
contact = """
phone
email
url
"""
class Partners(dd.Table):
...
detail_layout = PartnerDetail()
Each panel is a class attribute defined on your subclass, containing a string value to be used as template describing the content of that panel.
It can define more panels whose names may be chosen by the application
developer (just don't chose the name window_size
which has a
special meaning, and don't start your panel names with an underscore
because these are reserved for internal use).
Panels are either horizontal or vertical, depending on whether their template contains at least one newline character or not.
Indentation doesn't matter.
If the main panel of a FormLayout
is horizontal,
ExtJS will render the Layout using as a tabbed main panel.
If you want a horizontal main panel instead, just insert
a newline somewhere in your main's template. Example:
class NoteLayout(dd.FormLayout):
left = """
date type subject
person company
body
"""
right = """
uploads.UploadsByController
cal.TasksByController
"""
# the following will create a tabbed main panel:
main = "left:60 right:30"
# to avoid a tabbed main panel, specify:
main = """
left:60 right:30
"""
Glossary¶
- detail layout
The layout of a detail window. See The layout of a detail window
- column layout
The string that specifies how The columns of a table are laid out.