Source code for yarhp.sqla
#!/usr/bin/python
# -*- coding: utf-8 -*-
from decimal import Decimal
from pyramid.httpexceptions import HTTPOk, HTTPNotFound, HTTPConflict, \
HTTPCreated
from sqlalchemy.exc import IntegrityError
from yarhp import paginate, wrappers
from yarhp.view import BaseView
from yarhp.utils import get_composite_key
[docs]def get_model_schema(model):
"""Returns a validation schema for the ``model``
the schema is a dict of dicts in the form of:
.. code-block:: python
{field_name1:{
'type':<python type>,
'required':<bool>,
'length':<int>}
field_name2:{
...
}
...
}
"""
from sqlalchemy import types as sqla_types
from datetime import date, datetime
type_map = {
sqla_types.Integer: int,
sqla_types.Numeric: Decimal,
sqla_types.BigInteger: int,
sqla_types.Boolean: bool,
sqla_types.Float: float,
sqla_types.String: str,
sqla_types.Text: str,
sqla_types.CHAR: str,
sqla_types.Enum: unicode,
sqla_types.Unicode: unicode,
sqla_types.Date: date,
sqla_types.DateTime: datetime,
}
schema = {}
for name in model.mapper.columns.keys():
col = model.mapper.get_property(name).columns[0]
schema[name] = dict(type=type_map.get(type(col.type)),
required=(not col.nullable and not col.server_default),
length=getattr(col.type, 'length', None))
return schema
[docs]class SQLAView(BaseView):
"""Yarhp view used to serve SQLAlchemy objects.
``SQLAView implements the following logic:
default behaviour for all actions
validation agaisnt the sqla model's schema
"""
_default_actions = frozenset('index show delete create update'.split())
[docs] def validation_schema(self):
"Returns the validation schema dict"
schema = get_model_schema(self.__model_class__)
# update the model's schema with the one supplied in view's __validation_schema__
schema.update(self.__validation_schema__)
self.__validation_schema__ = schema
return self.__validation_schema__
[docs] def default_index(self, **kw):
"""default for index action.
Returns sqla query object which is passed to the pager to paginate the results.
"""
return self.__model_class__.query.filter_by(**kw)
[docs] def default_show(self, **kw):
"""default for show action.
Raises HTTPNotFound if the row is not found.
Returns the resouce as python dict.
"""
key = get_composite_key(self.__model_class__, kw)
self.active_obj = self.__model_class__.get(key)
if not self.active_obj:
raise HTTPNotFound()
return self.active_obj.to_dict()
[docs] def default_delete(self, **kw):
"""default for delete action.
Raises HTTPNotFound if the row is not found.
Returns HTTPOk on success.
"""
key = get_composite_key(self.__model_class__, kw)
self.active_obj = self.__model_class__.get(key)
if not self.active_obj:
raise HTTPNotFound()
self.active_obj.delete()
return HTTPOk()
[docs] def default_create(self, **kw):
"""default for create action.
Raises HTTPConflict if there is an integrity error in DB.
Returns HTTPCreated on success.
"""
params = self.request.params.copy()
params.update(kw)
self.active_obj = self.__model_class__(**params)
def location(params):
return self.request.route_url(self.resource.action_route_map['show'],
**params)
try:
self.active_obj.save()
params['id'] = self.active_obj.id
return HTTPCreated(location=location(params))
except IntegrityError:
raise HTTPConflict(location=location(params))
[docs] def default_update(self, **kw):
"""default for update action.
Raises HTTPNotFound if the resource being updated is not found.
Returns HTTPOk on success.
"""
key = get_composite_key(self.__model_class__, kw)
self.active_obj = self.__model_class__.get(key)
if not self.active_obj:
raise HTTPNotFound()
params = self.request.params.copy()
params.update(kw)
self.active_obj.update(**params)
self.active_obj.save()
return HTTPOk()