Models and fields
A model is a Python class that describes one kind of record, such as a customer or an invoice. Its fields describe the values each record holds.
#A first model
Create apps/shop/models/customer.py:
from evlet import Boolean, Email, Integer, Model, Rule, Text
class Customer(Model):
permissions = {
'admin': Rule(('read', 'create', 'update', 'delete')),
'editor': Rule(('read', 'create', 'update')),
'viewer': Rule(('read',)),
}
customer_name = Text(required=True, max_length=120)
email = Email()
credit_days = Integer(default=30, minimum=0, maximum=120)
active = Boolean(default=True)
class Meta:
title_field = 'customer_name'
list_fields = ('customer_name', 'email', 'active')
search_fields = ('customer_name', 'email')That is all Evlet needs. From this class it makes:
- a table called
customer, the class name in lower case; - a list page showing
list_fields, with search oversearch_fields; - a record page and form with every field, in the order you wrote them;
- the API routes under
/api/customer.
Evlet finds models by itself. Every Model class in a module under models/ is registered. Use one file per model to keep things easy to find.
#Field types
| Field | Holds |
|---|---|
Text | A short line of text. Set max_length. |
LongText | Longer plain text. |
RichText | Formatted text: headings, lists, links. Cleaned on every save. |
Integer | A whole number. |
Decimal | An exact decimal number with a fixed scale (places after the point), 0 to 9. The default is 4. |
Currency | An amount of money. currency='AED' names the code shown beside it. |
Percent | A percentage, stored as the number you see: 12.5 means 12.5%. |
Boolean | True or false. |
Date, DateTime, Time | A date, a moment in time (stored in UTC) or a time of day. |
Select | One value from a fixed list of choices. |
MultiSelect, Tags | Several values. |
Email, URL, Phone | Text with a format check. |
Link | A pointer to a record of another model. See Links and children. |
Image | One image, such as a product photo. |
Numbers are exact. Decimal, Currency and Percent never use floating point, and Evlet never rounds a value someone typed. A value with too many decimal places is refused, not rounded.
#Field options
Every field takes these options:
| Option | Meaning |
|---|---|
required=True | The field must have a value. |
default=... | The value for a new record when none is given. It can be a function, such as date.today. |
unique=True | No two records may share the value. |
index=True | Add a database index, for fields you filter on often. |
validator=... | A function that checks the value. See Validation. |
label, help_text | What the form shows. |
Number fields also take minimum and maximum. Text fields take max_length.
#Meta options
The Meta class inside a model holds settings that are not fields:
| Option | Meaning |
|---|---|
label, plural | The model's name in the browser, such as 'Item' and 'Items'. |
title_field | The field that names a record in lists, links and page titles. |
list_fields | The default columns of the list page. |
search_fields | The fields the list search looks in. |
#Names Evlet keeps for itself
Every record already has an id, which Evlet creates. Records also have a standard name. Do not call one of your fields name: installation refuses it and suggests a name such as customer_name instead.
#Records are snapshots
A record you read is a snapshot. You never change it in place. To change a record, save new values through the API, the browser or a context:
with app.business.context(user) as context:
customer = context.create(Customer, customer_name='Acme Trading', email='ops@example.com')
context.update(Customer, customer['id'], credit_days=45)update returns a new snapshot with the saved values.
#Changing a model later
Adding, removing or changing a field changes the database table, so it needs a migration. A change to labels, list settings or permissions does not. See Migrations.