Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Version 1¶
The database structure¶
The database structure is one of the first things you can do together with your customer before even starting to write code.
Here is a textual representation of the database structure:
Products : one row for every product or service. A product has a name (description) and a delivery unit.
Members : the people who use this site to register their offers and demands. For each member we record their name and email, and the place where they are located.
An Offer is when a given member declares that they want to sell a given product.
A Demand is when a given member declares that they want to buy a given product.
Each member is located in a given Place because we want to add filtering on offers and demands limited to a place.
Here is a graphical representation of the database structure. There are many methodologies for visualizing a database model (UML, IDEF1X), but the following is our favourite because it is simple, intuitive and useful.
![digraph foo {
graph [renderer="neato"]
node [shape=box]
node [style=filled]
node [fontname="times bold", fillcolor=red]
Product Member
node [fontname="times" fillcolor=gold] Offer Demand
node [fontname="times italic" fillcolor=lightblue] Place
Product -> Offer[arrowhead="inv"]
Product -> Demand[arrowhead="inv"]
Offer -> Member[taillabel="provider", labelangle="-90", labeldistance="2"];
Demand -> Member[taillabel="customer", labelangle="90", labeldistance="2"];
Member -> Place;
}](../../_images/graphviz-48ade61f57a3771d3699b67761bca90280ee8505.png)
Above picture has been realized using graphviz. You might prefer Dia, which produces output like this:

How to read such a diagram:
Every node on the diagram represents a database model.
Every arrow on the diagram represents a foreign key (FK). We sometimes use the word pointer instead of foreign key because that’s more intuitive).
We display the name of a pointer only if it differs from the model it points to. For example the arrow from Offer to Product is a FK field called product, defined on the Offer model. We do not display the name product on our diagram because that would be a waste of place.
We use three colors for grouping the models into three “data categories”:
red is for master data (i.e. relatively stable data)
yellow is for moving data (i.e. data that changes relatively often)
blue is for configuration data (i.e. data that is rather in background and accessible only to site managers)
The main page¶
The main page or “dashboard” is another thing you can discuss with your customer before even starting to write code. Let’s say that they want it to show a list of products available for exchange. Something like this:
Designation |
Offers |
Demands |
---|---|---|
Bread |
||
Buckwheat |
||
Eggs |
||
Electricity repair work |
The first prototype¶
Until here we have been analysts. The job of an analyst is to describe what a software product is supposed to do.
With above information a Lino application developer is able to write a prototype (“proof of concept”, “minimum viable product”). For this tutorial we wrote that prototype for you. You can run it by saying:
$ go lets1
$ pm prep
$ runserver
Now let’s have a look at the source code and make remarks about it.
The settings.py
file¶
The settings.py file is the first place to look when you want to discover a Django application . Here you can see for example which plugins are installed.
Our file says:
def get_installed_plugins(self):
yield super().get_installed_plugins()
yield 'lino_book.projects.lets1.lib.users'
yield 'lino_book.projects.lets1.lib.market'
You see that our LETS application has two plugins, “users” and “market”.
Every Lino plugin is a Python package and therefore has an __init__.py
file. In a Lino plugin, this file must define a class object named
Plugin
, which must be a subclass of lino.core.plugin.Plugin
.
The purpose of this class object is to integrate the plugin into your
application. You do this by defining menu items, quick links and dashboard
items.
You can see that we decided to use the lino.modlib.users
plugin for
storing what the customer calls “members”. But just extend it a bit:
we change the verbose model name from “User” to “Member”
we add a field
place
, which is a pointer to our table of places.
Every plugin has a models.py
file, which defines the database
models.
Most plugins also define tables, and usually you define them in a separate
module, called ui.py
.
And last but not least it’s important to define some demo data.
Not finished¶
The remaining sections are work in progress. Sorry.
The delivery_unit
field is a choicelist field. This is similar to a
foreign key, but instead of pointing to a database row, it points to a
choice in a hard-coded table, which we call a choicelist. See
Introduction to choicelists.
Form layouts¶
Note the detail_layout attributes of certain tables. They define the layout of the detail window for these database models (a detail window is what Lino opens when the user double-clicks on a given row).

The detail window of a Product should show the data fields and two slave tables, one showing the the offers and another with the demands for this product.
Here is the application code that produces the picture on the right
detail_layout = """
id name
OffersByProduct DemandsByProduct
"""
The dashboard¶

The dashboard shows the ActiveProducts table. The definition of that table is
here,
and the get_dashboard_items
method is defined
here)
More screenshots¶
Here are some screenshots.





Filtering¶
Some hints:
Note that the Offers, Demands and Products tables now have a
icon in their toolbar. This is the main new feature. Play with it.
The
Model.get_simple_parameters
method (a class method on a database model) yields the name of database fields to be used as “table parameters”, i.e. the fields that appear in the “parameter panel” (the panel that expands and collapses when you hit thebutton). See Introduction to actor parameters.
More¶
Maybe some helpful hints:
More about the application menu How plugins build the application menu
appypod : Generate printable documents from odt templates export_excel : Exporting to Excel
Verify¶
Actually even your simple prototype contains more than two plugins.
You can run the following code snippets in a Django shell session. If this was new for you, read Playing with the Django shell.
>>> from lino.api.doctest import *
>>> pprint(settings.SITE.installed_plugins)
(<lino.core.plugin.Plugin lino>,
<lino.modlib.about.Plugin lino.modlib.about>,
<lino.modlib.jinja.Plugin lino.modlib.jinja(needed by lino_react.react)>,
<lino_react.react.Plugin lino_react.react(needs ['lino.modlib.jinja'])>,
<lino.modlib.printing.Plugin lino.modlib.printing(needed by lino.modlib.system)>,
<lino.modlib.system.Plugin lino.modlib.system(needed by lino_book.projects.lets1.lib.users, needs ['lino.modlib.printing'])>,
<lino_book.projects.lets1.lib.users.Plugin lino_book.projects.lets1.lib.users(needs ['lino.modlib.system'])>,
<lino_book.projects.lets1.lib.market.Plugin lino_book.projects.lets1.lib.market>,
<lino.core.plugin.Plugin django.contrib.staticfiles>,
<lino.core.plugin.Plugin django.contrib.sessions>)
In reality is has more plugins because Lino installs certain plugins automatically, and because one plugin can require other plugins.