chapps.dbmodels module
CHAPPS data schemata
Database schema expressed as SQLAlchemy ORM Models
Basic data models correspond to Pydantic models for API, but more models are required for the database side:
There is a subclass of the metaclass,
DeclarativeMeta
, which provides extra logic to the database models to automate common queries and tasks.There are table definitions for the join tables.
There is a special class for generalizing the logic of joining the tables.
- chapps.dbmodels.convention = {'ck': 'ck_%(table_name)s_%(constraint_name)s', 'fk': 'fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s', 'ix': 'ix_%(column_0_label)s', 'pk': 'pk_%(table_name)s', 'uq': 'uq_%(table_name)s_%(column_0_name)s'}
SQLA’s recommended naming convention for constraints
- class chapps.dbmodels.DB_Customizations[source]
Bases:
sqlalchemy.orm.decl_api.DeclarativeMeta
Custom ORM metaclass
In order to make common tasks more concise, and to conceal the need for complex data massaging in order to produce appropriate data structures for the different kinds of queries, a fair amount of custom code is introduced into the ORM models via this metaclass. These routines allow calls to the ORM class itself, to get it to return statement objects (objects defined in
sqlalchemy.sql.expression
).- windowed_list_by_ids(*, ids=[], subquery=None, skip=0, limit=1000, q='%')[source]
SELECT a window of objects
- Parameters
- Raises
ValueError – unless one of
ids
orsubquery
is provided- Returns
a
Select
implementing the window- Return type
sqlalchemy.sql.expression.Select
If both of
subquery
andids
are not empty,subquery
prevails andids
is ignored.
- select_by_ids(ids, assoc=None)[source]
Return a select statement for a list of objects, optionally with eager-loaded associations
- select_by_pattern(q)[source]
Return a Select for all records with names which include
q
as a substring- Parameters
q (str) –
- select_by_name(q)[source]
Return a Select for the record whose name exactly matches
q
- Parameters
q (str) –
- windowed_list(q='%', skip=0, limit=1000)[source]
Return a Select for a window of
select_by_pattern()
- update_by_id(item)[source]
Return an Update statement for the specified item
- Parameters
cls (type) – an ORM model class (subclass of
DB_Base
)item (cls) – an instance of an ORM model of the type stored in
cls
- Returns
an
Update
statement object representing the new values ofitem
- Return type
sqlalchemy.sql.expression.Update
- chapps.dbmodels.DB_Base
DB_Base serves as the base of all ORM models
This class itself contains literally no code apart from documentation. All of the magic provided for the ORM layer is implemented in the metaclass,
DB_Customizations
. To be clear, all of the methods defined in the metaclass become available as class methods on the classes derived fromDB_Base
, because it is of typeDB_Customizations
.
- chapps.dbmodels.quota_user = Table('quota_user', MetaData(), Column('user_id', Integer(), ForeignKey('users.id'), table=<quota_user>, primary_key=True, nullable=False), Column('quota_id', Integer(), ForeignKey('quotas.id'), table=<quota_user>, nullable=False), schema=None)
the
quota_user
join table
- chapps.dbmodels.domain_user = Table('domain_user', MetaData(), Column('user_id', Integer(), ForeignKey('users.id'), table=<domain_user>, primary_key=True, nullable=False), Column('domain_id', Integer(), ForeignKey('domains.id'), table=<domain_user>, primary_key=True, nullable=False), schema=None)
the
domain_user
join table
- chapps.dbmodels.email_user = Table('email_user', MetaData(), Column('user_id', Integer(), ForeignKey('users.id'), table=<email_user>, primary_key=True, nullable=False), Column('email_id', Integer(), ForeignKey('emails.id'), table=<email_user>, primary_key=True, nullable=False), schema=None)
the
email_user
join table
- class chapps.dbmodels.Quota[source]
Bases:
sqlalchemy.orm.decl_api.Base
ORM Model for Quota definitions
Each record/instance has these columns/attributes:
- id
integer primary key
- name
unique string of 32 chars or less
- quota
unique integer transmission attempt limit
- __init__(**kwargs)
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- class chapps.dbmodels.Domain[source]
Bases:
sqlalchemy.orm.decl_api.Base
ORM Model for Domain definitions
Each record/instance has these columns/attributes:
- id
integer primary key
- name
unique string of 64 chars or less
- greylist
if True perform greylisting
- check_spf
if True perform SPF enforcement
- __init__(**kwargs)
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- class chapps.dbmodels.Email[source]
Bases:
sqlalchemy.orm.decl_api.Base
ORM Model for Email definitions
Each record/instance has these columns/attributes:
- id
integer primary key
- name
unique string of 128 chars or less
- __init__(**kwargs)
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- class chapps.dbmodels.User[source]
Bases:
sqlalchemy.orm.decl_api.Base
ORM model for User objects
Each record/instance has these columns/attributes:
- id
integer auto-incremented primary key
- name
unique string of up to 128 chars
- quota
associated Quota object; there can be only one Quota associated to a User
- domains
list of associated Domain objects
a User may be associated to more than one Domain, and a Domain may be associated to more than one User
- emails
list of associated Email objects
a User may be associated to more than one Email, and an Email may be associated to more than one User
- __init__(**kwargs)
A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and values in
kwargs
.Only keys that are present as attributes of the instance’s class are allowed. These could be, for example, any mapped columns or relationships.
- class chapps.dbmodels.JoinAssoc[source]
Bases:
object
Represent joining two data tables via a two-column join table
There is probably some way to use SQLA for this but I am using it wrongly, to avoid loading associations just in order to link them to other objects via a join table
- __init__(source_model, source_id, *, assoc_name, assoc_type, assoc_model, assoc_id, table)[source]
Define a join association
- Parameters
source_model (DB_Base) – a reference to the dbmodel class of the source object
source_id (str) – label of the source object’s ID column in the join table
assoc_name (str) – attribute name of the association
assoc_type (type) – usually
int
orList[int]
; should be the type for the API to expect when setting up the route metadataassoc_model (DB_Base) – a reference to the dbmodel class of the associated object
assoc_id (str) – label of associated object’s ID column in the join table
table (sqlalchemy.schema.Table) – a reference to the join table schema; it will be a constant in this module, generally
- select()[source]
Convenience method
- Returns
a SELECT on the join table
- Return type
sqlalchemy.sql.expression.Select
- insert()[source]
Convenience method
- Returns
an INSERT on the join table
- Return type
sqlalchemy.sql.expression.Insert
- delete()[source]
Convenience method
- Returns
a DELETE FROM on the join table
- Return type
sqlalchemy.sql.expression.Delete
- update()[source]
Convenience method
- Returns
an UPDATE on the join table
- Return type
sqlalchemy.sql.expression.Update
- values(item, assoc)[source]
Get value-insertion or update mapping
- Parameters
- Return type
Using the
item
passed in, which may be an ORM object descended fromDB_Base
or anint
, construct a list of dictionaries mapping the join table’s ID column names correctly onto the source item ID and the associated item ID(s).
- property source_col
- property assoc_col