Skip to main content

Pyramid framework integration to extend SQLAlchemy ORM classes with separate, easily testable, code.

Project description

Good frameworks, like [Pyramid][] and [Angular][], help developers write
testable code. [SQLAlchemy][] is a great framework. However, the sheer
convenience of having model instances returned from a database query
encourages developers to write large ORM classes which can be hard to test.

One way to avoid this is to keep model classes [thin][] and write separate code
to instantiate and manipulate them. The downside of this approach is the loss in
convenience: the separated, easily testable code isn't provided by default as
an attribute of the model instances returned from a database query.

[pyramid_alchemy][] provides an `add_model_method` Pyramid
[configuration directive]() that extends [SQLAlchemy ORM][] classes in the same
way that `add_request_method` [extends the Pyramid Request][]. Using this
directive allows developers to write easily testable code that is conveniently
available as a model instance attribute. For example, if you [include][] this
in your Pyramid application:

```python
from .model import Spam

def get_eggs(instance, source='hens', limit=9, offset=0):
"""Example ORM instance method, implemented as a standalone function."""

query = instance.query.filter_by(source=source)
return query.offset(offset).limit(limit)

def includeme(config):
config.add_model_method(Spam, get_eggs, 'get_eggs')
```

You can then use the `get_eggs` method from `Spam` instances:

```python
spam = Session.query(Spam).get(1)
eggs = spam.get_eggs()
```

### Interfaces

Just as you can hang a Pyramid view off any context object implementing a
specific interface, you can extend any model instance implementing an interface.
For example, if your model looked something like this:

```python
from sqlalchemy.ext.declarative import declarative_base
from zope.interfaces import implementer

from .interfaces import IFilling

Base = declarative_base()

@implementer(IFilling)
class Ham(Base):
# ...

@implementer(IFilling)
class Spam(Base):
# ...
```

Then you could extend all fillings -- current and future -- with:

```python
config.add_model_method(IFilling, get_eggs, 'get_eggs')
```

### Limitations

Note that it's highly unlikely to be a good idea to use `add_model_method` to
add dynamic or hybrid methods that affect the underlying sql table or mapping.

[Pyramid]: http://docs.pylonsproject.org/projects/pyramid/en/latest
[Angular]: http://angularjs.org
[SQLAlchemy]: http://docs.sqlalchemy.org/en/latest
[pyramid_alchemy]: https://github.com/thruflo/pyramid_alchemy
[configuration directive]: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/extconfig.html
[SQLAlchemy ORM]: http://docs.sqlalchemy.org/en/latest/orm
[extends the Pyramid Request]: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/config.html#pyramid.config.Configurator.add_request_method
[include]: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/config.html#pyramid.config.Configurator.include
[thin]: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyramid_alchemy-0.0.1.tar.gz (4.0 kB view details)

Uploaded Source

File details

Details for the file pyramid_alchemy-0.0.1.tar.gz.

File metadata

File hashes

Hashes for pyramid_alchemy-0.0.1.tar.gz
Algorithm Hash digest
SHA256 6806b9090af3dca6aa06e843b86ba684e419d2d752178215bb28bb0527d794ca
MD5 1c3416e4aa3f2fc9dc46a8d96dde234b
BLAKE2b-256 e08c73d4653d611a6ec93e20e1ab35fff340fd24c63cf5ba79e12f4ee4b07cb7

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page