Sustained.py

A Python query builder inspired by Objection.js

View the Project on GitHub wetherc/sustained

The Model class is the foundation of sustained.py. Each model you create represents a database table.

<– Back to Index

Basic Setup

To define a model, create a class that inherits from sustained.Model and give it a tableName.

from sustained import Model

class Person(Model):
    # This is the only required property.
    tableName = 'persons'

class Animal(Model):
    tableName = 'animals'

Namespace Properties

For fully qualified table names, you can also specify database and tableSchema.

class User(Model):
    database = 'my_db'
    tableSchema = 'public'
    tableName = 'users'

# This model will produce queries like:
# SELECT * FROM my_db.public.users
print(User.query())

These properties are used by the QueryBuilder to construct the FROM clause of your SQL queries.

Dynamic Model Creation

In some cases, you might need to create models at runtime. The create_model function is provided for this purpose. It takes the desired class name and table name as arguments.

from sustained import create_model, RelationType

# A simple dynamic model
Vehicle = create_model('Vehicle', 'vehicles')

# You can use it immediately
query = Vehicle.query().select('id', 'license_plate')
print(query)
# SELECT id, license_plate FROM vehicles


# You can also define relations for dynamic models
Person = create_model('Person', 'persons')

Animal = create_model(
    'Animal',
    'animals',
    mappings={
        'owner': {
            'relation': RelationType.BelongsToOneRelation,
            'modelClass': Person,
            'join': {'from': 'animals.ownerId', 'to': 'persons.id'}
        }
    }
)

# This works just like a statically defined model
query = Animal.query().innerJoinRelated('owner')
print(query)
# SELECT * FROM animals INNER JOIN persons ON animals.ownerId = persons.id

Column Name Access

Model instances provide a convenient way to get fully-qualified column names for use in queries, which helps avoid ambiguity.

person = Person()

# Accessing an attribute on a model instance returns the qualified column name
print(person.id)
# "persons.id"

# Use it in a select statement
query = Person.query().select(person.firstName, person.lastName)
print(query)
# SELECT persons.firstName, persons.lastName FROM persons

If the model has a database or tableSchema defined, they will be included in the qualified name.

user = User() # The model with `database` and `tableSchema`
print(user.id)
# "my_db.public.users.id"

This feature is particularly useful for writing complex joins and where clauses while ensuring you’re always referencing the correct column.