Docs

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:

Python
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 over search_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

FieldHolds
TextA short line of text. Set max_length.
LongTextLonger plain text.
RichTextFormatted text: headings, lists, links. Cleaned on every save.
IntegerA whole number.
DecimalAn exact decimal number with a fixed scale (places after the point), 0 to 9. The default is 4.
CurrencyAn amount of money. currency='AED' names the code shown beside it.
PercentA percentage, stored as the number you see: 12.5 means 12.5%.
BooleanTrue or false.
Date, DateTime, TimeA date, a moment in time (stored in UTC) or a time of day.
SelectOne value from a fixed list of choices.
MultiSelect, TagsSeveral values.
Email, URL, PhoneText with a format check.
LinkA pointer to a record of another model. See Links and children.
ImageOne 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:

OptionMeaning
required=TrueThe 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=TrueNo two records may share the value.
index=TrueAdd a database index, for fields you filter on often.
validator=...A function that checks the value. See Validation.
label, help_textWhat 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:

OptionMeaning
label, pluralThe model's name in the browser, such as 'Item' and 'Items'.
title_fieldThe field that names a record in lists, links and page titles.
list_fieldsThe default columns of the list page.
search_fieldsThe 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:

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