Dictalchemy package

Introduction

This library adds basic functionality for getting a dict from an SQLAlchemy model and updating a model from a dict.

SQLAlchemy is a very complex library. It contains synonyms, lists, sets, mixins and god knows what. Automatically convert that to a dict or update from a dict is not a simple task. This library should not be used on more complex models without thorough testing, it should however be fine to use on simple models.

Usage

There are two ways to use dictalchemy. Either by using dictalchemy.classes.DictableModel as base class or by using dictalchemy.utils.make_class_dictable() on an existing base class.

The actual work is done in the functions dictalchemy.utils.asdict() and dictalchemy.utils.fromdict().

Since attributes are checked on instances each instance can get their own setup of rules. This can be useful when returning a model instance as a response. If default values are set on that specific instance calling dict will render it properly.

Using DictableModel

Use dictalchemy.classes.DictableModel as a base class for sqlalchemy.ext.declarative_base.

Example:

from sqlalchemy.ext import declarative_base
from dictalchemy import DictableModel
Base = declarative_base(cls=DictableModel)

Using make_class_dictable

dictalchemy.utils.make_class_dictable() adds methods and attributes to an already existing class

Example:

from sqlalchemy.ext import declarative_base
from dictalchemy import make_class_dictable
base = declarative_base()
make_class_dictable(base)

Attributes and parameters

Dictalchemy uses some basic attributes and parameters to convert to and from dict. The most basic are:

  • include
  • exclude
  • exclude_pk
  • allow_pk
  • follow
  • only

The defaults varies depending on the flag. For example, allow_pk will by default be set to True for fromdict and exclude_pk will be set to False in asdict.

A class or model can have these attributes set, prefixed with dictalchemy_. Some of them can also be overridden depending on if dictalchemy.utils.asdict() or dictalchemy.utils.fromdict() is called. If they are set they will override the more basic attribute.

Some semi-rules
  • In general include flags will override exclude flags.
  • In general only will override exclude and include flags.
  • In dictalchemy.utils.fromdict() `allow_pk`=False will override all other flags.
Class/Model attributes
  • dictalchemy_exclude
  • dictalchemy_include
  • dictalchemy_fromdict_include
  • dictalchemy_asdict_include
  • dictalchemy_exclude_underscore
  • dictalchemy_fromdict_allow_pk

A note about synonyms

Synonyms wraps a reader and a writer method. These methods can do whatever they want to so there is no way to safely updated data with synonyms. So keep in mind that using synonyms will make it possible to circumvent for example dictalchemy_exclude_pk.

Bugs and missing features

This library is developed as a helper-library to another piece of software. What works for that software is also implemented and tested in dictalchemy.

There are bugs and missing features in this library. Please don’t hesitate to register issues at github.

Classes

Contains DictableModel that can be used as a base class for sqlalchemy.ext.declarative_base().

class dictalchemy.classes.DictableModel[source]

Bases: object

Can be used as a base class for sqlalchemy.ext.declarative()

Contains the methods DictableModel.__iter__(), DictableModel.asdict() and DictableModel.fromdict().

Example usage:

>>> from dictalchemy import DictableModel
>>> from slqlachemy.ext.declarative import declarative_base
>>> Base = declarative_base(cls=DictableModel)
Variables:
  • dictalchemy_exclude – List of properties that should always be excluded.
  • dictalchemy_exclude_underscore – If True properties starting with an underscore will always be excluded.
  • dictalchemy_fromdict_allow_pk – If True the primary key can be updated by DictableModel.fromdict().
  • dictalchemy_asdict_include – List of properties that should always be included when calling DictableModel.asdict()
  • dictalchemy_fromdict_include – List of properties that should always be included when calling DictableModel.fromdict()
asdict(model, exclude=None, exclude_underscore=None, exclude_pk=None, follow=None, include=None, only=None)

Get a dict from a model

Simple example:

session.query(User).asdict()
{'id': 1, 'username': 'Gerald'}

Using exclude_pk:

session.query(User).asdict(exclude_pk=True)
{'username': 'Gerald'}

Using exclude:

session.query(User).asdict(exclude=['id'])
{'username': 'Gerald'}

Using follow without arguments:

session.query(User).asdict(follow={'groups':{}})
{'username': 'Gerald', groups=[{'id': 1, 'name': 'User'}]}

Using follow with arguments:

session.query(User).asdict(follow={'groups':{'exclude': ['id']})
{'username': 'Gerald', groups=[{'name': 'User'}]}

Using include(for example for including synonyms/properties):

session.query(User).asdict(include=['displayname']
{'id': 1, 'username': 'Gerald', 'displayname': 'Gerald'}
Parameters:
  • follow – List or dict of relationships that should be followed. If the parameter is a dict the value should be a dict of keyword arguments. Currently it follows InstrumentedList, MappedCollection and regular 1:1, 1:m, m:m relationships.
  • exclude – List of properties that should be excluded, will be merged with model.classes.DictableModel.dictalchemy_exclude
  • exclude_pk – If True any column that refers to the primary key will be excluded.
  • exclude_underscore – Overides model.dictalchemy_exclude_underscore if set
  • include – List of properties that should be included. Use this to allow python properties to be called. This list will be merged with model.dictalchemy_asdict_include or model.dictalchemy_include.
  • only – List of properties that should be included. This will override everything else except follow.
Raises :

dictalchemy.errors.MissingRelationError if follow contains a non-existent relationship.

Raises :

dictalchemy.errors.UnsupportedRelationError If follow contains an existing relationship that currently isn’t supported.

Returns:

dict

fromdict(model, data, exclude=None, exclude_underscore=None, allow_pk=None, follow=None, include=None, only=None)

Update a model from a dict

Works almost identically as dictalchemy.utils.asdict(). However, it will not create missing instances or update collections.

This method updates the following properties on a model:

  • Simple columns
  • Synonyms
  • Simple 1-m relationships
Parameters:
  • data – dict of data
  • exclude – list of properties that should be excluded
  • exclude_underscore – If True underscore properties will be excluded, if set to None model.dictalchemy_exclude_underscore will be used.
  • allow_pk – If True any column that refers to the primary key will be excluded. Defaults model.dictalchemy_fromdict_allow_pk or dictable.constants.fromdict_allow_pk. If set to True a primary key can still be excluded with the exclude parameter.
  • follow – Dict of relations that should be followed, the key is the arguments passed to the relation. Relations only works on simple relations, not on lists.
  • include – List of properties that should be included. This list will override anything in the exclude list. It will not override allow_pk.
  • only – List of the only properties that should be returned. This will not override allow_pk or follow.
Raises :

dictalchemy.DictalchemyError If a primary key is in data and allow_pk is False

Returns:

The model

Utilities

dictalchemy.utils.asdict(model, exclude=None, exclude_underscore=None, exclude_pk=None, follow=None, include=None, only=None)[source]

Get a dict from a model

Simple example:

session.query(User).asdict()
{'id': 1, 'username': 'Gerald'}

Using exclude_pk:

session.query(User).asdict(exclude_pk=True)
{'username': 'Gerald'}

Using exclude:

session.query(User).asdict(exclude=['id'])
{'username': 'Gerald'}

Using follow without arguments:

session.query(User).asdict(follow={'groups':{}})
{'username': 'Gerald', groups=[{'id': 1, 'name': 'User'}]}

Using follow with arguments:

session.query(User).asdict(follow={'groups':{'exclude': ['id']})
{'username': 'Gerald', groups=[{'name': 'User'}]}

Using include(for example for including synonyms/properties):

session.query(User).asdict(include=['displayname']
{'id': 1, 'username': 'Gerald', 'displayname': 'Gerald'}
Parameters:
  • follow – List or dict of relationships that should be followed. If the parameter is a dict the value should be a dict of keyword arguments. Currently it follows InstrumentedList, MappedCollection and regular 1:1, 1:m, m:m relationships.
  • exclude – List of properties that should be excluded, will be merged with model.classes.DictableModel.dictalchemy_exclude
  • exclude_pk – If True any column that refers to the primary key will be excluded.
  • exclude_underscore – Overides model.dictalchemy_exclude_underscore if set
  • include – List of properties that should be included. Use this to allow python properties to be called. This list will be merged with model.dictalchemy_asdict_include or model.dictalchemy_include.
  • only – List of properties that should be included. This will override everything else except follow.
Raises :

dictalchemy.errors.MissingRelationError if follow contains a non-existent relationship.

Raises :

dictalchemy.errors.UnsupportedRelationError If follow contains an existing relationship that currently isn’t supported.

Returns:

dict

dictalchemy.utils.fromdict(model, data, exclude=None, exclude_underscore=None, allow_pk=None, follow=None, include=None, only=None)[source]

Update a model from a dict

Works almost identically as dictalchemy.utils.asdict(). However, it will not create missing instances or update collections.

This method updates the following properties on a model:

  • Simple columns
  • Synonyms
  • Simple 1-m relationships
Parameters:
  • data – dict of data
  • exclude – list of properties that should be excluded
  • exclude_underscore – If True underscore properties will be excluded, if set to None model.dictalchemy_exclude_underscore will be used.
  • allow_pk – If True any column that refers to the primary key will be excluded. Defaults model.dictalchemy_fromdict_allow_pk or dictable.constants.fromdict_allow_pk. If set to True a primary key can still be excluded with the exclude parameter.
  • follow – Dict of relations that should be followed, the key is the arguments passed to the relation. Relations only works on simple relations, not on lists.
  • include – List of properties that should be included. This list will override anything in the exclude list. It will not override allow_pk.
  • only – List of the only properties that should be returned. This will not override allow_pk or follow.
Raises :

dictalchemy.DictalchemyError If a primary key is in data and allow_pk is False

Returns:

The model

dictalchemy.utils.get_column_keys(model)[source]

Get column keys for a model

Returns:List of column keys
dictalchemy.utils.get_primary_key_properties(model)[source]

Get the column properties that affects a primary key

Returns:Set of column keys
dictalchemy.utils.get_relation_keys(model)[source]

Get relation keys for a model

Returns:List of RelationProperties
dictalchemy.utils.get_synonym_keys(model)[source]

Get synonym keys for a model

Returns:List of keys for synonyms
dictalchemy.utils.iter(model)[source]

iter method for models

dictalchemy.utils.make_class_dictable(cls, exclude=None, exclude_underscore=True, fromdict_allow_pk=False, include=None, asdict_include=None, fromdict_include=None)[source]

Make a class dictable

Useful for when the Base class is already defined, for example when using Flask-SQLAlchemy.

Warning: This method will overwrite existing attributes if they exists.

Parameters:
  • exclude – Will be set as dictalchemy_exclude on the class
  • exclude_underscore – Will be set as dictalchemy_exclude_underscore on the class
  • fromdict_allow_pk – Will be set as dictalchemy_fromdict_allow_pk on the class
  • include – Will be set as dictalchemy_include on the class.
  • asdict_include – Will be set as dictalchemy_asdict_include on the class. If not None it will override dictalchemy_include.
  • fromdict_include – Will be set as dictalchemy_fromdict_include on the class. If not None it will override dictalchemy_include.
Returns:

The class

Errors

exception dictalchemy.errors.DictalchemyError[source]

Bases: exceptions.Exception

Base class for Dictalchemy errors

exception dictalchemy.errors.MissingRelationError(relation_key)[source]

Bases: dictalchemy.errors.DictalchemyError

Raised when a relationship is missing

The name of the relation can be accessed from ‘relation_key’

exception dictalchemy.errors.UnsupportedRelationError(relation_key)[source]

Bases: dictalchemy.errors.DictalchemyError

Raised when a relation is not supported by asdict or fromdict.

The name of the relation can be accessed from ‘relation_key’