API Reference¶
Model¶
Declarative base for ORM models.
-
class
alchy.model.ModelMeta(name, bases, dct)[source]¶ ModelBase’s metaclass which provides:
- Tablename autogeneration when
__tablename__not defined. - Support for multiple database bindings via
ModelBase.__bind_key__. - Support for declarative ORM events via
alchy.eventsdecorators orModelBase.__events__.
- Tablename autogeneration when
-
class
alchy.model.ModelBase(*args, **kargs)[source]¶ Base class for creating a declarative base for models.
To create a declarative base:
# in project/core.py from alchy import ModelBase, make_declarative_base class Base(ModelBase): # augument the ModelBase with super powers pass Model = make_declarative_base(Base=Base) # in project/models/user.py from project.core import Model class User(Model): # define declarative User model pass
-
__table_args__¶ Default table args.
-
__mapper_args__¶ Define a default order by when not specified by query operation, e.g.:
{ 'order_by': [column1, column2] }
-
__bind_key__¶ Bind a model to a particular database URI using keys from
Manager.config['SQLALCHEMY_BINDS']. By default a model will be bound toManager.config['SQLALCHEMY_DATABASE_URI'].
-
__events__¶ Register orm event listeners. See
alchy.eventsfor more details.
-
query_class¶ Query class to use for
self.query.
-
query¶ An instance of
query_class. Can be used to query the database for instances of this model. NOTE: Requires settingMyClass.query = QueryProperty(session)when session available. Seemake_declarative_base()for automatic implementation.
-
__to_dict__¶ Configuration for
to_dict(). Do any necessary preprocessing and return a set of string attributes which represent the fields which should be returned when callingto_dict().By default this model is refreshed if it’s
__dict__state is empty and only the ORM descriptor fields are returned.This is the property to override if you want to return more/less than the default ORM descriptor fields.
Generally, we can usually rely on
__dict__as a representation of model when it’s just been loaded from the database. In this case, whatever values are present in__dict__are the loaded values from the database which include/exclude lazy attributes (columns and relationships).One issue to be aware of is that after a model has been committed (or expired),
__dict__will be empty. This can be worked around by callingrefresh()which will reload the data from the database using the default loader strategies.These are the two main cases this default implementation will try to cover. For anything more complex it would be best to override this property or the
to_dict()method itself.
-
classmethod
column_attrs()[source]¶ Return table columns as list of class attributes at the class level.
-
descriptor_dict¶ Return
__dict__key-filtered bydescriptors.
-
classmethod
get_by(data_dict=None, **kargs)[source]¶ Return first instance filtered by values using
cls.query.filter_by().
-
object_session¶ Return session belonging to
self
-
classmethod
primary_key()[source]¶ Return primary key as either single column (one primary key) or tuple otherwise.
-
query_class alias of
QueryModel
-
to_dict()[source]¶ Return dict representation of model by filtering fields using
__to_dict__.
-
Query¶
Query subclass used by Manager as default session query class.
-
class
alchy.query.Query(entities, session=None)[source]¶ Extension of default Query class used in SQLAlchemy session queries.
-
DEFAULT_PER_PAGE= 50¶ Default per_page argument for pagination when per_page not specified.
-
all_entities¶ Return list of entities + join_entities present in query.
-
entities¶ Return list of entity classes present in query.
-
immediateload(*keys, **kargs)[source]¶ Apply
immediateload()to keys.Parameters: keys (mixed) – Either string or column references to join path(s). Keyword Arguments: options (list) – A list of LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.Note
Additional keyword args will be passed to initial load creation.
-
join_eager(*keys, **kargs)[source]¶ Apply
join+self.options(contains_eager()).Parameters: keys (mixed) – Either string or column references to join path(s).
Keyword Arguments: - alias –
Join alias or
dictmapping key names to aliases. - options (list) –
A list of
LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.
- alias –
Join alias or
-
join_entities¶ Return list of the joined entity classes present in query.
-
joinedload(*keys, **kargs)[source]¶ Apply
joinedload()to keys.Parameters: keys (mixed) – Either string or column references to join path(s). Keyword Arguments: options (list) – A list of LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.Note
Additional keyword args will be passed to initial load creation.
-
lazyload(*keys, **kargs)[source]¶ Apply
lazyload()to keys.Parameters: keys (mixed) – Either string or column references to join path(s). Keyword Arguments: options (list) – A list of LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.Note
Additional keyword args will be passed to initial load creation.
-
noload(*keys, **kargs)[source]¶ Apply
noload()to keys.Parameters: keys (mixed) – Either string or column references to join path(s). Keyword Arguments: options (list) – A list of LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.Note
Additional keyword args will be passed to initial load creation.
-
outerjoin_eager(*keys, **kargs)[source]¶ Apply
outerjoin+self.options(contains_eager()).Parameters: keys (mixed) – Either string keys or column references to join path(s).
Keyword Arguments: - alias –
Join alias or
dictmapping key names to aliases. - options (list) –
A list of
LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.
- alias –
Join alias or
-
paginate(page=1, per_page=None, error_out=True)[source]¶ Return
Paginationinstance using already defined query parameters.
-
subqueryload(*keys, **kargs)[source]¶ Apply
subqueryload()to keys.Parameters: keys (mixed) – Either string or column references to join path(s). Keyword Arguments: options (list) – A list of LoadOptionto apply to the overall load strategy, i.e., eachLoadOptionwill be chained at the end of the load.Note
Additional keyword args will be passed to initial load creation.
-
-
class
alchy.query.QueryModel(entities, session=None)[source]¶ Class used for default query property class for
mymanager.query,mymanager.session.query, andMyModel.query. Can be used in other libraries/implementations when creating a session:from sqlalchemy import orm from alchy import QueryModel # or if not using as query property # from alchy import Query session = orm.scoped_session(orm.sessionmaker()) session.configure(query_cls=QueryModel)
NOTE: If you don’t plan to use the query class as a query property, then you can use the
Queryclass instead since it won’t include features that only work within a query property context.-
__search_filters__¶ All available search filter functions indexed by a canonical name which will be referenced in advanced/simple search. All filter functions should take a single value and return an SQLAlchemy filter expression, i.e.,
{key: lambda value: Model.column_name.contains(value)}
-
__advanced_search__¶ Advanced search models search by named parameters. Generally found on advanced search forms where each field maps to a specific database field that will be queried against. If defined as a list, each item should be a key from
__search_filters__. The matching__search_filters__function will be used in the query. If defined as a dict, it should have the same format as__search_filters__.
-
__simple_search__¶ Simple search models search by phrase (like Google search). Defined like
__advanced_search__.
-
__order_by__¶ Default order-by to use when
alchy.model.ModelBase.queryused.
-
Model¶ Return primary entity model class.
-
advanced_filter(search_dict=None)[source]¶ Return the compiled advanced search filter mapped to search_dict.
-
get_search_filters(keys)[source]¶ Return
__search_filters__filtered by keys.
-
-
class
alchy.query.QueryProperty(session)[source]¶ Query property accessor which gives a model access to query capabilities via
alchy.model.ModelBase.querywhich is equivalent tosession.query(Model).
-
class
alchy.query.Pagination(query, page, per_page, total, items)[source]¶ Internal helper class returned by
Query.paginate(). You can also construct it from any other SQLAlchemy query object if you are working with other libraries. Additionally it is possible to passNoneas query object in which case the prev and next will no longer work.-
has_next= None¶ True if a next page exists.
-
has_prev= None¶ True if a previous page exists.
-
items= None¶ The items for the current page.
-
next(error_out=False)[source]¶ Returns a
Paginationobject for the next page.
-
next_num= None¶ Number of the next page.
-
page= None¶ The current page number (1 indexed).
-
pages= None¶ The total number of pages.
-
per_page= None¶ The number of items to be displayed on a page.
-
prev(error_out=False)[source]¶ Returns a
Paginationobject for the previous page.
-
prev_num= None¶ Number of the previous page.
-
query= None¶ The query object that was used to create this pagination object.
-
total= None¶ The total number of items matching the query.
-
-
class
alchy.query.LoadOption(strategy, *args, **kargs)[source]¶ Chained load option to apply to a load strategy when calling
Queryload methods.Example usage:
qry = (db.session.query(Product) .join_eager('category', options=[LoadOption('noload', 'images')]))
This would result in the
noloadoption being chained to the eager option forProduct.categoryand is equilvalent to:qry = (db.session.query(Product) .join('category') .options(contains_eager('category').noload('images')))
Events¶
Declarative ORM event decorators and event registration.
SQLAlchemy features an ORM event API but one thing that is lacking is a way to register event handlers in a declarative way inside the Model’s class definition. To bridge this gap, this module contains a collection of decorators that enable this kind of functionality.
Instead of having to write event registration like this:
from sqlalchemy import event
from project.core import Model
class User(Model):
_id = Column(types.Integer(), primary_key=True)
email = Column(types.String())
def set_email_listener(target, value, oldvalue, initiator):
print 'received "set" event for target: {0}'.format(target)
return value
def before_insert_listener(mapper, connection, target):
print 'received "before_insert" event for target: {0}'.format(target)
event.listen(User.email, 'set', set_email_listener, retval=True)
event.listen(User, 'before_insert', before_insert_listener)
Model Events allows one to write event registration more succinctly as:
from alchy import events
from project.core import Model
class User(Model):
_id = Column(types.Integer(), primary_key=True)
email = Column(types.String())
@events.on_set('email', retval=True)
def on_set_email(target, value, oldvalue, initiator):
print 'received set event for target: {0}'.format(target)
return value
@events.before_insert()
def before_insert(mapper, connection, target):
print ('received "before_insert" event for target: {0}'
.format(target))
For details on each event type’s expected function signature, see SQLAlchemy’s ORM Events.
-
class
alchy.events.on_append(attribute, **event_kargs)[source]¶ Event decorator for the
appendevent.
-
class
alchy.events.on_remove(attribute, **event_kargs)[source]¶ Event decorator for the
removeevent.
-
class
alchy.events.before_delete(name, attribute, listener, kargs)[source]¶ Event decorator for the
before_deleteevent.
-
class
alchy.events.before_insert(**event_kargs)[source]¶ Event decorator for the
before_insertevent.
-
class
alchy.events.before_update(**event_kargs)[source]¶ Event decorator for the
before_updateevent.
-
class
alchy.events.before_insert_update(**event_kargs)[source]¶ Event decorator for the
before_insertandbefore_updateevents.
-
class
alchy.events.after_insert_update(**event_kargs)[source]¶ Event decorator for the
after_insertandafter_updateevents.
-
class
alchy.events.on_append_result(**event_kargs)[source]¶ Event decorator for the
append_resultevent.
-
class
alchy.events.on_create_instance(**event_kargs)[source]¶ Event decorator for the
create_instanceevent.
-
class
alchy.events.on_instrument_class(**event_kargs)[source]¶ Event decorator for the
instrument_classevent.
-
class
alchy.events.before_configured(**event_kargs)[source]¶ Event decorator for the
before_configuredevent.
-
class
alchy.events.after_configured(**event_kargs)[source]¶ Event decorator for the
after_configuredevent.
-
class
alchy.events.on_mapper_configured(**event_kargs)[source]¶ Event decorator for the
mapper_configuredevent.
-
class
alchy.events.on_populate_instance(**event_kargs)[source]¶ Event decorator for the
populate_instanceevent.
Search¶
SQLAlchemy query filter factories usable in
alchy.query.QueryModel.__search_filters__.
These are factory functions that return common filter operations as functions which are then assigned to the model class’ search config attributes. These functions are syntatic sugar to make it easier to define compatible search functions. However, due to the fact that a model’s query class has to be defined before the model and given that the model column attributes need to be defined before using the search factories, there are two ways to use the search factories on the query class:
- Define
alchy.query.QueryModel.__search_filters__as a property that returns the filter dict. - Pass in a callable that returns the column.
For example, without alchy.search one would define a
alchy.query.QueryModel.__search_filters__ similar to:
class UserQuery(QueryModel):
__search_filters = {
'email': lambda value: User.email.like(value)
}
class User(Model):
query_class = UserQuery
email = Column(types.String(100))
Using alchy.search the above then becomes:
class UserQuery(QueryModel):
@property
def __search_filters__(self):
return {
'email': like(User.email)
}
class User(Model):
query_class = UserQuery
email = Column(types.String(100))
Or if a callable is passed in:
from alchy import search
class UserQuery(QueryModel):
__search_filters__ = {
'email': like(lambda: User.email)
}
class User(Model):
query_class = UserQuery
email = Column(types.String(100))
The general naming convention for each comparator is:
The basic call signature for the search functions is:
# search.<function>(column)
# e.g.
search.contains(email)
-
class
alchy.search.notlike(column)[source]¶ Return
not(like)filter function using ORM column field.
-
class
alchy.search.notilike(column)[source]¶ Return
not(ilike)filter function using ORM column field.
-
class
alchy.search.startswith(column)[source]¶ Return
startswithfilter function using ORM column field.
-
class
alchy.search.notstartswith(column)[source]¶ Return
not(startswith)filter function using ORM column field.
-
class
alchy.search.endswith(column)[source]¶ Return
endswithfilter function using ORM column field.
-
class
alchy.search.notendswith(column)[source]¶ Return
not(endswith)filter function using ORM column field.
-
class
alchy.search.contains(column)[source]¶ Return
containsfilter function using ORM column field.
-
class
alchy.search.notcontains(column)[source]¶ Return
not(contains)filter function using ORM column field.
-
class
alchy.search.icontains(column)[source]¶ Return
icontainsfilter function using ORM column field.
-
class
alchy.search.noticontains(column)[source]¶ Return
not(icontains)filter function using ORM column field.
-
class
alchy.search.any_(column, column_operator)[source]¶ Return
anyfilter function using ORM relationship field.
-
class
alchy.search.notany_(column, column_operator)[source]¶ Return
not(any)filter function using ORM relationship field.
-
class
alchy.search.has(column, column_operator)[source]¶ Return
hasfilter function using ORM relationship field.
-
class
alchy.search.nothas(column, column_operator)[source]¶ Return
not(has)filter function using ORM relationship field.
Types¶
Collection of custom column types.
-
class
alchy.types.DeclarativeEnumType(enum, name=None)[source]¶ Column type usable in table column definitions.
-
class
alchy.types.DeclarativeEnum[source]¶ Declarative enumeration.
For example:
class OrderStatus(DeclarativeEnum): pending = ('p', 'Pending') submitted = ('s', 'Submitted') complete = ('c', 'Complete') class Order(Model): status = Column(OrderStatus.db_type(), default=OrderStatus.pending)
-
classmethod
db_type(name=None)[source]¶ Return database column type for use in table column definitions.
-
classmethod
from_string(string)[source]¶ Return enum symbol given string value.
Raises: ValueError– If string doesn’t correspond to an enum value.
-
classmethod
values()[source]¶ Return list of possible enum values. Each value is a valid argument to
from_string().
-
classmethod
Manager¶
Manager class and mixin.
The Manager class helps manage a SQLAlchemy database session as well
as provide convenience functions for commons operations.
Configuration¶
The following configuration values can be passed into a new Manager
instance as a dict, class, or module.
SQLALCHEMY_DATABASE_URI |
URI used to connect to the database. Defaults to
sqlite://. |
SQLALCHEMY_BINDS |
A dict that maps bind keys to database URIs.
Optionally, in place of a database URI, a
configuration dict can be used to overrided
connection options. |
SQLALCHEMY_ECHO |
When True have SQLAlchemy echo all SQL
statements. Defaults to False. |
SQLALCHEMY_POOL_SIZE |
The size of the database pool. Defaults to the
engine’s default (usually 5). |
SQLALCHEMY_POOL_TIMEOUT |
Specifies the connection timeout for the pool.
Defaults to 10. |
SQLALCHEMY_POOL_RECYCLE |
Number of seconds after which a connection is automatically recycled. |
SQLALCHEMY_MAX_OVERFLOW |
Controls the number of connections that can be created after the pool reached its maximum size. When those additional connections are returned to the pool, they are disconnected and discarded. |
-
class
alchy.manager.ManagerMixin[source]¶ Extensions for
Manager.session.-
add(*instances)[source]¶ Override
session.add()so it can function likesession.add_all().Note
Supports chaining.
-
-
class
alchy.manager.Manager(config=None, session_options=None, Model=None, session_class=None)[source]¶ Manager class for database session.
Initialization of
Manageraccepts a config object, session options, and an optional declarative base. IfModelisn’t provided, then a default one is generated usingalchy.model.make_declarative_base(). The declarative base model is accessible atModel.By default the
session_optionsare:{ 'query_cls': alchy.Query, 'autocommit': False, 'autoflush': True }
The default
session_classisalchy.Session. If you want to provide your own session class, then it’s suggested that you subclassalchy.Sessionand pass it in viasession_class. This way your subclass will inherit the functionality ofalchy.Session.-
Model= None¶ Declarative base model class.
-
binds¶ Returns config options for all binds.
-
binds_map¶ Returns a dictionary with a table->engine mapping. This is suitable for use in
sessionmaker(binds=binds_map).
-
config= None¶ Database engine configuration options.
-
create_engine(uri_or_config)[source]¶ Create engine using either a URI or a config dict. If URI supplied, then the default
configwill be used. If config supplied, then URI in config will be used.
-
create_scoped_session(options=None)[source]¶ Create scoped session which internally calls
create_session().
-
create_session(options)[source]¶ Create session instance using custom Session class that supports multiple bindings.
-
engine¶ Return default database engine.
-
get_engine(bind=None)[source]¶ Return engine associated with bind. Create engine if it doesn’t already exist.
-
session= None¶ Scoped session object.
-
session_class= None¶ Class to used for session object.
-
Session¶
Session class that supports multiple database binds.
-
class
alchy.session.Session(manager, **options)[source]¶ The default session used by
alchy.manager.Manager. It extends the default session system with bind selection.
Utils¶
Generic utility functions used in package.
-
alchy.utils.is_sequence(obj)[source]¶ Test if obj is an iterable but not
dictorstr. Mainly used to determine if obj can be treated like alistfor iteration purposes.
-
alchy.utils.has_primary_key(metadict)[source]¶ Check if meta class’ dict object has a primary key defined.