Moved majority of the docs to doc blocks

This commit is contained in:
Konsta Vesterinen
2013-10-30 15:10:44 +02:00
parent 24e624749d
commit eba82c16e0
11 changed files with 373 additions and 323 deletions

View File

@@ -54,379 +54,89 @@ Data types
SQLAlchemy-Utils provides various new data types for SQLAlchemy. SQLAlchemy-Utils provides various new data types for SQLAlchemy.
.. module:: sqlalchemy_utils.types
ChoiceType ChoiceType
^^^^^^^^^^ ^^^^^^^^^^
ChoiceType offers way of having fixed set of choices for given column. Columns with ChoiceTypes are automatically coerced to Choice objects. .. module:: sqlalchemy_utils.types.choice
.. autoclass:: ChoiceType
::
class User(self.Base):
TYPES = [
(u'admin', u'Admin'),
(u'regular-user', u'Regular user')
]
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
type = sa.Column(ChoiceType(TYPES))
user = User(type=u'admin')
user.type # Choice(type='admin', value=u'Admin')
ChoiceType is very useful when the rendered values change based on user's locale:
::
from babel import lazy_gettext as _
class User(self.Base):
TYPES = [
(u'admin', _(u'Admin')),
(u'regular-user', _(u'Regular user'))
]
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
type = sa.Column(ChoiceType(TYPES))
user = User(type=u'admin')
user.type # Choice(type='admin', value=u'Admin')
print user.type # u'Admin'
ColorType ColorType
^^^^^^^^^ ^^^^^^^^^
ColorType provides a way for saving Color (from colour_ package) objects into database. .. module:: sqlalchemy_utils.types.color
ColorType saves Color objects as strings on the way in and converts them back to objects when querying the database.
:: .. autoclass:: ColorType
from colour import Color
from sqlalchemy_utils import ColorType
class Document(Base):
__tablename__ = 'document'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
background_color = sa.Column(ColorType)
document = Document()
document.background_color = Color('#F5F5F5')
session.commit()
Querying the database returns Color objects:
::
document = session.query(Document).first()
document.background_color.hex
# '#f5f5f5'
For more information about colour package and Color object, see https://github.com/vaab/colour
JSONType JSONType
^^^^^^^^ ^^^^^^^^
JSONType offers way of saving JSON data structures to database. On PostgreSQL the underlying implementation of this data type is 'json' while on other databases its simply 'text'. .. module:: sqlalchemy_utils.types.json
:: .. autoclass:: JSONType
from sqlalchemy_utils import JSONType
class Product(Base):
__tablename__ = 'product'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
details = sa.Column(JSONType)
product = Product()
product.details = {
'color': 'red',
'type': 'car',
'max-speed': '400 mph'
}
session.commit()
LocaleType LocaleType
^^^^^^^^^^ ^^^^^^^^^^
LocaleType saves Babel_ Locale objects into database. The Locale objects are converted to string on the way in and back to object on the way out.
In order to use LocaleType you need to install Babel_ first. .. module:: sqlalchemy_utils.types.locale
::
from sqlalchemy_utils import LocaleType
from babel import Locale
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
locale = sa.Column(LocaleType)
user = User()
user.locale = Locale('en_US')
session.commit()
Like many other types this type also supports scalar coercion:
::
user.locale = 'de_DE'
user.locale # Locale('de_DE')
.. autoclass:: LocaleType
NumberRangeType NumberRangeType
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
NumberRangeType provides way for saving range of numbers into database. .. module:: sqlalchemy_utils.types.number_range
Example ::
from sqlalchemy_utils import NumberRangeType, NumberRange
class Event(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(255))
estimated_number_of_persons = sa.Column(NumberRangeType)
party = Event(name=u'party')
# we estimate the party to contain minium of 10 persons and at max
# 100 persons
party.estimated_number_of_persons = NumberRange(10, 100)
print party.estimated_number_of_persons
# '10-100'
NumberRange supports some arithmetic operators:
::
meeting = Event(name=u'meeting')
meeting.estimated_number_of_persons = NumberRange(20, 40)
total = (
meeting.estimated_number_of_persons +
party.estimated_number_of_persons
)
print total
# '30-140'
.. autoclass:: NumberRangeType
ScalarListType ScalarListType
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
ScalarListType type provides convenient way for saving multiple scalar values in one .. module:: sqlalchemy_utils.types.scalar_list
column. ScalarListType works like list on python side and saves the result as comma-separated list
in the database (custom separators can also be used).
Example ::
from sqlalchemy_utils import ScalarListType
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
hobbies = sa.Column(ScalarListType())
user = User()
user.hobbies = [u'football', u'ice_hockey']
session.commit()
You can easily set up integer lists too:
::
from sqlalchemy_utils import ScalarListType
class Player(Base):
__tablename__ = 'player'
id = sa.Column(sa.Integer, autoincrement=True)
points = sa.Column(ScalarListType(int))
player = Player()
player.points = [11, 12, 8, 80]
session.commit()
.. autoclass:: ScalarListType
URLType URLType
^^^^^^^ ^^^^^^^
URLType stores furl_ objects into database. .. module:: sqlalchemy_utils.types.url
::
from sqlalchemy_utils import URLType
from furl import furl
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
website = sa.Column(URLType)
user = User(website=u'www.example.com')
# website is coerced to furl object, hence all nice furl operations come
# available
user.website.args['some_argument'] = '12'
print user.website
# www.example.com?some_argument=12
.. autoclass:: URLType
UUIDType UUIDType
^^^^^^^^ ^^^^^^^^
UUIDType will store a UUID in the database in a native format, if available,
or a 16-byte BINARY column or a 32-character CHAR column if not.
:: .. module:: sqlalchemy_utils.types.uuid
from sqlalchemy_utils import UUIDType .. autoclass:: UUIDType
import uuid
class User(Base):
__tablename__ = 'user'
# Pass `binary=False` to fallback to CHAR instead of BINARY
id = sa.Column(UUIDType(binary=False), primary_key=True)
TimezoneType TimezoneType
^^^^^^^^^^^^ ^^^^^^^^^^^^
TimezoneType provides a way for saving timezones (from either the pytz or the dateutil package) objects into database.
TimezoneType saves timezone objects as strings on the way in and converts them back to objects when querying the database.
.. module:: sqlalchemy_utils.types.timezone
:: .. autoclass:: TimezoneType
from sqlalchemy_utils import UUIDType
class User(Base):
__tablename__ = 'user'
# Pass backend='pytz' to change it to use pytz (dateutil by default)
timezone = sa.Column(TimezoneType(backend='pytz'))
The generates decorator The generates decorator
----------------------- -----------------------
Many times you may have generated property values. Usual cases include slugs from names or resized thumbnails from images. .. module:: sqlalchemy_utils.decorators
SQLAlchemy-Utils provides a way to do this easily with `generates` decorator: .. autofunction:: generates
::
class Article(self.Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
slug = sa.Column(sa.Unicode(255))
@generates(slug)
def _create_slug(self):
return self.name.lower().replace(' ', '-')
article = self.Article()
article.name = u'some article name'
self.session.add(article)
self.session.flush()
assert article.slug == u'some-article-name'
You can also pass the attribute name as a string argument for `generates`:
::
class Article(self.Base):
...
@generates('slug')
def _create_slug(self):
return self.name.lower().replace(' ', '-')
These property generators can even be defined outside classes:
::
class Article(self.Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
slug = sa.Column(sa.Unicode(255))
@generates(Article.slug)
def _create_article_slug(self):
return self.name.lower().replace(' ', '-')
Or with lazy evaluated string argument:
::
@generates('Article.slug')
def _create_article_slug(self):
return self.name.lower().replace(' ', '-')
Generic Relationship Generic Relationship
@@ -478,10 +188,6 @@ Generic relationship is a form of relationship that supports creating a 1 to man
# Find any events that are bound to users. # Find any events that are bound to users.
session.query(Event).filter(Event.object.is_type(User)).all() session.query(Event).filter(Event.object.is_type(User)).all()
.. _Babel: http://babel.pocoo.org/
.. _furl: https://github.com/gruns/furl
.. _colour: https://github.com/vaab/colour .. _colour: https://github.com/vaab/colour

View File

@@ -8,6 +8,73 @@ listeners_registered = False
def generates(attr): def generates(attr):
"""
Many times you may have generated property values. Usual cases include
slugs from names or resized thumbnails from images.
SQLAlchemy-Utils provides a way to do this easily with `generates`
decorator:
::
class Article(self.Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
slug = sa.Column(sa.Unicode(255))
@generates(slug)
def _create_slug(self):
return self.name.lower().replace(' ', '-')
article = self.Article()
article.name = u'some article name'
self.session.add(article)
self.session.flush()
assert article.slug == u'some-article-name'
You can also pass the attribute name as a string argument for `generates`:
::
class Article(self.Base):
...
@generates('slug')
def _create_slug(self):
return self.name.lower().replace(' ', '-')
These property generators can even be defined outside classes:
::
class Article(self.Base):
__tablename__ = 'article'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
slug = sa.Column(sa.Unicode(255))
@generates(Article.slug)
def _create_article_slug(self):
return self.name.lower().replace(' ', '-')
Or with lazy evaluated string argument:
::
@generates('Article.slug')
def _create_article_slug(self):
return self.name.lower().replace(' ', '-')
"""
register_listeners() register_listeners()
def wraps(func): def wraps(func):

View File

@@ -28,6 +28,57 @@ class Choice(object):
class ChoiceType(types.TypeDecorator, ScalarCoercible): class ChoiceType(types.TypeDecorator, ScalarCoercible):
"""
ChoiceType offers way of having fixed set of choices for given column.
Columns with ChoiceTypes are automatically coerced to Choice objects.
::
class User(self.Base):
TYPES = [
(u'admin', u'Admin'),
(u'regular-user', u'Regular user')
]
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
type = sa.Column(ChoiceType(TYPES))
user = User(type=u'admin')
user.type # Choice(type='admin', value=u'Admin')
ChoiceType is very useful when the rendered values change based on user's
locale:
::
from babel import lazy_gettext as _
class User(self.Base):
TYPES = [
(u'admin', _(u'Admin')),
(u'regular-user', _(u'Regular user'))
]
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.Unicode(255))
type = sa.Column(ChoiceType(TYPES))
user = User(type=u'admin')
user.type # Choice(type='admin', value=u'Admin')
print user.type # u'Admin'
"""
impl = types.Unicode(255) impl = types.Unicode(255)
def __init__(self, choices, impl=None): def __init__(self, choices, impl=None):

View File

@@ -12,8 +12,41 @@ except ImportError:
class ColorType(types.TypeDecorator, ScalarCoercible): class ColorType(types.TypeDecorator, ScalarCoercible):
""" """
Changes Color objects to a string representation on the way in and ColorType provides a way for saving Color (from colour_ package) objects
changes them back to Color objects on the way out. into database. ColorType saves Color objects as strings on the way in and
converts them back to objects when querying the database.
::
from colour import Color
from sqlalchemy_utils import ColorType
class Document(Base):
__tablename__ = 'document'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
background_color = sa.Column(ColorType)
document = Document()
document.background_color = Color('#F5F5F5')
session.commit()
Querying the database returns Color objects:
::
document = session.query(Document).first()
document.background_color.hex
# '#f5f5f5'
For more information about colour package and Color object, see:
https://github.com/vaab/colour
""" """
STORE_FORMAT = u'hex' STORE_FORMAT = u'hex'
impl = types.Unicode(20) impl = types.Unicode(20)

View File

@@ -23,8 +23,32 @@ ischema_names['json'] = PostgresJSONType
class JSONType(sa.types.TypeDecorator): class JSONType(sa.types.TypeDecorator):
"Represents an immutable structure as a json-encoded string." """
JSONType offers way of saving JSON data structures to database. On
PostgreSQL the underlying implementation of this data type is 'json' while
on other databases its simply 'text'.
::
from sqlalchemy_utils import JSONType
class Product(Base):
__tablename__ = 'product'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
details = sa.Column(JSONType)
product = Product()
product.details = {
'color': 'red',
'type': 'car',
'max-speed': '400 mph'
}
session.commit()
"""
impl = sa.UnicodeText impl = sa.UnicodeText
def __init__(self): def __init__(self):

View File

@@ -11,8 +11,40 @@ except ImportError:
class LocaleType(types.TypeDecorator, ScalarCoercible): class LocaleType(types.TypeDecorator, ScalarCoercible):
""" """
Changes babel.Locale objects to a string representation on the way in and LocaleType saves Babel_ Locale objects into database. The Locale objects
changes them back to Locale objects on the way out. are converted to string on the way in and back to object on the way out.
In order to use LocaleType you need to install Babel_ first.
.. _Babel: http://babel.pocoo.org/
::
from sqlalchemy_utils import LocaleType
from babel import Locale
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(50))
locale = sa.Column(LocaleType)
user = User()
user.locale = Locale('en_US')
session.commit()
Like many other types this type also supports scalar coercion:
::
user.locale = 'de_DE'
user.locale # Locale('de_DE')
""" """
impl = types.Unicode(10) impl = types.Unicode(10)

View File

@@ -12,6 +12,48 @@ class NumberRangeRawType(types.UserDefinedType):
class NumberRangeType(types.TypeDecorator, ScalarCoercible): class NumberRangeType(types.TypeDecorator, ScalarCoercible):
"""
NumberRangeType provides way for saving range of numbers into database.
Example ::
from sqlalchemy_utils import NumberRangeType, NumberRange
class Event(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
name = sa.Column(sa.Unicode(255))
estimated_number_of_persons = sa.Column(NumberRangeType)
party = Event(name=u'party')
# we estimate the party to contain minium of 10 persons and at max
# 100 persons
party.estimated_number_of_persons = NumberRange(10, 100)
print party.estimated_number_of_persons
# '10-100'
NumberRange supports some arithmetic operators:
::
meeting = Event(name=u'meeting')
meeting.estimated_number_of_persons = NumberRange(20, 40)
total = (
meeting.estimated_number_of_persons +
party.estimated_number_of_persons
)
print total
# '30-140'
"""
impl = NumberRangeRawType impl = NumberRangeRawType
def process_bind_param(self, value, dialect): def process_bind_param(self, value, dialect):

View File

@@ -8,6 +8,50 @@ class ScalarListException(Exception):
class ScalarListType(types.TypeDecorator): class ScalarListType(types.TypeDecorator):
"""
ScalarListType type provides convenient way for saving multiple scalar
values in one column. ScalarListType works like list on python side and
saves the result as comma-separated list in the database (custom separators
can also be used).
Example ::
from sqlalchemy_utils import ScalarListType
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, autoincrement=True)
hobbies = sa.Column(ScalarListType())
user = User()
user.hobbies = [u'football', u'ice_hockey']
session.commit()
You can easily set up integer lists too:
::
from sqlalchemy_utils import ScalarListType
class Player(Base):
__tablename__ = 'player'
id = sa.Column(sa.Integer, autoincrement=True)
points = sa.Column(ScalarListType(int))
player = Player()
player.points = [11, 12, 8, 80]
session.commit()
"""
impl = sa.UnicodeText() impl = sa.UnicodeText()
def __init__(self, coerce_func=six.text_type, separator=u','): def __init__(self, coerce_func=six.text_type, separator=u','):

View File

@@ -6,8 +6,21 @@ from .scalar_coercible import ScalarCoercible
class TimezoneType(types.TypeDecorator, ScalarCoercible): class TimezoneType(types.TypeDecorator, ScalarCoercible):
""" """
Changes Timezone objects to a string representation on the way in and TimezoneType provides a way for saving timezones (from either the pytz or
changes them back to Timezone objects on the way out. the dateutil package) objects into database. TimezoneType saves timezone
objects as strings on the way in and converts them back to objects when
querying the database.
::
from sqlalchemy_utils import TimezoneType
class User(Base):
__tablename__ = 'user'
# Pass backend='pytz' to change it to use pytz (dateutil by default)
timezone = sa.Column(TimezoneType(backend='pytz'))
""" """
impl = types.CHAR(50) impl = types.CHAR(50)

View File

@@ -9,6 +9,34 @@ from .scalar_coercible import ScalarCoercible
class URLType(types.TypeDecorator, ScalarCoercible): class URLType(types.TypeDecorator, ScalarCoercible):
"""
URLType stores furl_ objects into database.
.. _furl: https://github.com/gruns/furl
::
from sqlalchemy_utils import URLType
from furl import furl
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
website = sa.Column(URLType)
user = User(website=u'www.example.com')
# website is coerced to furl object, hence all nice furl operations come
# available
user.website.args['some_argument'] = '12'
print user.website
# www.example.com?some_argument=12
"""
impl = types.UnicodeText impl = types.UnicodeText
def process_bind_param(self, value, dialect): def process_bind_param(self, value, dialect):

View File

@@ -9,8 +9,18 @@ class UUIDType(types.TypeDecorator, ScalarCoercible):
""" """
Stores a UUID in the database natively when it can and falls back to Stores a UUID in the database natively when it can and falls back to
a BINARY(16) or a CHAR(32) when it can't. a BINARY(16) or a CHAR(32) when it can't.
"""
::
from sqlalchemy_utils import UUIDType
import uuid
class User(Base):
__tablename__ = 'user'
# Pass `binary=False` to fallback to CHAR instead of BINARY
id = sa.Column(UUIDType(binary=False), primary_key=True)
"""
impl = types.BINARY(16) impl = types.BINARY(16)
python_type = uuid.UUID python_type = uuid.UUID