ERP5 Handbook/From form to API
From form to API - first look behind the scenes
Management inteface of a form
When 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
Simple 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:
invokes a method:
to get value of an attribute:
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:
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
A 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
so it invokes accessor:
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:
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:
and has a funny behaviour, which will be explained somewhere else.
Category membership fields and API
Some 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:
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: