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;

}

Above picture has been realized using graphviz. You might prefer Dia, which produces output like this:

../../_images/models.png

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

Fred

Buckwheat

Fred, Anne

Henri

Eggs

Henri, Mari

Electricity repair work

Henri, Argo

The main menu

And a last thing to discuss is the main menu. For the LETS website it will be fairly simple:

  • Master:

    • Products – show the list of products

    • Members – show the list of members

  • Market

    • Offers – show the full list of all offers

    • Demands – show the full list of all demands

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).

../../_images/t3a-3.jpg

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

../../_images/a.png

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.

../../_images/b.png ../../_images/c.png ../../_images/d.png ../../_images/e.png ../../_images/members_insert.png

Filtering

Some hints:

  • Note that the Offers, Demands and Products tables now have a gear 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 the gear button). 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.