ERP5 Handbook/From form to API
From form to API - first look behind the scenes
editManagement interface of a form
editWhen you look at the ERP5 screen, what you see is a rendered form (ERP5 Form, which is based on a Formulator form). Its name is usually at the end of the URL (like "Person_viewCareer"); often, the URL ends with "/view", which means that you are looking at the default form of an object. If you see a number of tabs (like "View / Details / Career"), click on any of them and you will have the form name in the URL. If you are in a module and there is no tabs, things are a bit more difficult, we will come to that a bit later.
Once you have the form name, append "/manage_main" to it - now you are in a management screen, and you have a complete list of fields which are visible in on the form (and possibly some which are not visible).
We won't be talking in detail about editing a form - you can consult Formulator documentation for that. The purpose here is show how fields are filled with values, and how they interact with the object.
Property fields and API
editSimple fields - those containing strings, numbers, or checkboxes with boolean values, are bound to object attributes by naming convention. When a field is rendered, it invokes an appropriate accessor to get an attribute value. This is why all controls begin with "my_" - a field:
my_title
invokes a method:
.getTitle
to get value of an attribute:
title
Most of the accessors are auto-generated (see "Magic of ERP5" to know more) - if a property "title" is defined, an object has the accessor, but you won't find it in the code (!). Sometimes accessors are overwritten - e.g. a Person object has a different .getTitle method. This one you can find in the code.
When a form is submitted, and you had changed value of a "title" field, the script which is being called by the form (usu. "Base_edit") invokes a setter:
.setTitle
which, not surprisingly, sets the title. Replace the form_name/manage_main with "/Base_viewDict" - you will see raw data of the object, and you will find your title.
That's almost all there is to it. There is a number of special fields for different types of attributes - there is a StringField, TextAreaField, IntField, FloatField, DateField, EmailField. These fields check if the value you've entered is appropriate.
Relation fields and API
editA relation field (specifically, RelationStringField) has already been described in UI section. Basically, it follows the same principle as property fields. The difference is that in most cases a relation field used for relation
source
is called
my_source_title
so it invokes accessor:
.getSourceTitle
the result being that it displays a nice title of the related object, instead of its relative url (like "/organisation_module/12"). And conversely, when you fill it and submit a form, it uses the title to search for the appropriate object.
You can also apply the same convention to use other properties then title, e.g. you could create a field:
my_source_relative_url
which will display and use a relative url of a related object.
There is also a MultiRelationStringField, which is used to get/set a relation to many objects:
my_destination_title_list
uses
.getDestinationTitleList
and has a funny behaviour, which will be explained somewhere else.
Category membership fields and API
editSome fields allow you to assign an object to certain categories (in other words, to use categories for classification). For example, you can set a product_line on a product, or nationality on a person. For this purpose, a ListField is used. It follows the same principle:
my_nationality
allows you to choose a nationality, and it assigns the person to a chosen subcategory of "nationality" base category.
The way to field such a control with values is to give it a list of tuples containing title and url of categories, like:
'', '', ['German', 'd'], ['British', 'en']...
This is most easily achieved through the category's API; most commonly used method are:
.getCategoryChildLogicalPathItemList and getCategoryChildCompactLogicalPathItemList
The latter different from the former in that if the path made of titles becomes too long, it tries to trim it in a reasonable way.
A MultiListField works the same way, only it allows for selecting many categories (by ctrl-clicking), and, obviously, uses a:
.get[category]List
accessor.