Models

Most of the time we encounter the same model types:

BaseModels

Models are mainly a collection of Attibute with some specificities about how the data is stored. Each model holds a mapping attribute, basically a persistent dict, where each Attibute has an entry where its content is stored. The key each attribute use can be set with the attribute key argument. Generally it is not needed to explicitely set this key because your model will inherit from a class that will do this automatically for you:

This means that if you want to change the name of an attribute in a NamedAttributesModel, or change the order of an attribute in an IntAttributesModel you will need to explicitely set the key it has before remaning/moving. Else sheraf won’t be able to correctly retrieve your data.

Here is an example: First we define models without bothering with setting explicit keys.

>>> class StringAttributesCowboy(sheraf.NamedAttributesModel, sheraf.UUIDIndexedModel, sheraf.IndexedModel):
...     table = "string_attributes_cowboys"
...
...     name = sheraf.StringAttribute()  # The implicit key is 'name'
...     email = sheraf.StringAttribute()  # The implicit key is 'email'
...
>>> class IntAttributesCowboy(sheraf.IntAttributesModel, sheraf.UUIDIndexedModel, sheraf.IndexedModel):
...     table = "int_attributes_cowboys"
...
...     name = sheraf.StringAttribute()  # The implicit key is '0'
...     email = sheraf.StringAttribute()  # The implicit key is '1'
...
>>> with sheraf.connection(commit=True):
...     george = StringAttributesCowboy.create(name="George", email="george@abitbol.com")
...     peter = IntAttributesCowboy.create(name="Peter", email="peter@sheraf.com")

Then we change the name of the email attribute in StringAttributesCowboy, and we change the order of the attributes in IntAttributesCowboy. To make previous data still accessible, we need to update the attribute keys so they stay as they were.

>>> class StringAttributesCowboy(sheraf.NamedAttributesModel, sheraf.UUIDIndexedModel, sheraf.IndexedModel):
...     table = "string_attributes_cowboys"
...
...     name = sheraf.StringAttribute()
...     awesome_email = sheraf.StringAttribute(key="email")
...
>>> class IntAttributesCowboy(sheraf.IntAttributesModel, sheraf.UUIDIndexedModel, sheraf.IndexedModel):
...     table = "int_attributes_cowboys"
...
...     email = sheraf.StringAttribute(key=1)
...     name = sheraf.StringAttribute(key=0)
...
>>> with sheraf.connection():
...     assert StringAttributesCowboy.read(george.id).awesome_email == "george@abitbol.com"
...     assert IntAttributesCowboy.read(peter.id).email == "peter@sheraf.com"

IndexableModel

The indexation capabilities of the models are held by BaseIndexedModel. This class allows the use of methods like read(), read(), search() or filter(). Indexable models needs to be indexed somewhere in the database. Sheraf allows several places for a model to be stored:

To retrieve an indexed model, it must have at least one Index on which to search for. This is why sheraf requires exactly one index which attribute primary is True. Primary index are like regular unique indexes, but it will be used by default in several contexts like the read() method.

Sheraf offers several classes with a primary index already set:

  • UUIDIndexedModel has a id primary index which is a StringUUIDAttribute. This means that by default an objet created with this class will have a id attribute, that will hold a str representing a UUID. The commonly used Model inherits from this class.

  • IntIndexedModel has a id primary index that is an int randomly choosen.

  • IntOrderedIndexedModel has a id primary index that is an increasing int. The first id will be 0, the second will be 1 and so on.