Reading the doc of sqlalchemy, i saw the serialization part.
I'm wondering about a possibility to use an xml serializer for matching sa models with Rest webservices like Jax-RS
There is a django extension which deal with that : django_roa
Do you know if that kind of thing has already been developped for sqlalchemy or if is it possible to do it??
Thanks
Its a long way till full RFC2616 compliance, but for a prototype, I do something like this:
from sqlalchemy import create_engine, Table, Column, Integer, String, ForeignKey, UniqueConstraint
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, backref, sessionmaker
from sqlalchemy.sql.expression import desc
import web
import json
DB_PATH = 'sqlite:////tmp/test.db'
Base = declarative_base()
class LocalClient(Base):
__tablename__ = 'local_clients'
__jsonexport__ = ['id', 'name', 'password']
id = Column(Integer, primary_key=True)
name = Column(String, unique=True, nullable=False)
password = Column(String)
def __init__(self, name, password):
self.name = name
self.password = password
def __repr__(self):
return "<LocalClient('%s', '%s')>" % (self.name, self.password)
urls = (
'/a/LocalClient', 'LocalClientsController'
)
class Encoder(json.JSONEncoder):
'''This class contains the JSON serializer function for user defined types'''
def default(self, obj):
'''This function uses the __jsonexport__ list of relevant attributes to serialize the objects that inherits Base'''
if isinstance(obj, Base):
return dict(zip(obj.__jsonexport__, [getattr(obj, v) for v in obj.__jsonexport__]))
return json.JSONEncoder.default(self, obj)
class LocalClientsController:
'''The generic RESTful Local Clients Controller'''
def GET(self):
'''Returns a JSON list of LocalClients'''
engine = create_engine(DB_PATH, echo=False)
Session = sessionmaker(bind=engine)
session = Session()
clis = session.query(LocalClient)
return json.dumps([c for c in clis], cls=Encoder)
sqlalchemy.ext.serializer exists to support pickling (with pickle module) of queries, expressions and other internal SQLAlchemy objects, it doesn't deal with model objects. In no way it will help you to serialize model objects to XML. Probably something like pyxser will be useful for you.
Related
To create the User table I have to use drop_all and then create_all methods. But these two functions re-initiate an entire database. I wonder if there is a way to create the User table without erasing (or dropping) any existing tables in a database?
import sqlalchemy
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
name = sqlalchemy.Column(sqlalchemy.String)
def __init__(self, code=None, *args, **kwargs):
self.name = name
url = 'postgresql+psycopg2://user:pass#01.02.03.04/my_db'
engine = sqlalchemy.create_engine(url)
session = sqlalchemy.orm.scoped_session(sqlalchemy.orm.sessionmaker())
session.configure(bind=engine, autoflush=False, expire_on_commit=False)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
You can create/drop individual tables:
User.__table__.drop(engine)
User.__table__.create(engine)
from app import db
from models import User
User.__table__.create(db.engine)
User.__table__.drop(db.engine)
Another way to accomplish the task:
Base.metadata.tables['users'].create(engine)
Base.metadata.tables['users'].drop(engine)
I was wondering if it is possible to use SqlAlchemy's automap_base() in the following way:
from sqlalchemy.ext.automap import automap_base
from sqlalchemy import create_engine
# automap base
Base = automap_base()
# pre-declare User for the 'user' table
class User(Base):
__tablename__ = 'user'
def __str__(self):
return self.name
def greet(self):
return 'Hello {}!'.format(self.name)
def add_address(self, address):
'''Utilizes the auto reflected relationship to add
a new address with a proper user_id to table "addresses"'''
self.address_collection.append(address)
# reflect
engine = create_engine("sqlite:///mydatabase.db")
# only to generate attributes and relationships
Base.prepare(engine, reflect=True)
So I would like to reflect the data and the relationships from the database, but extend the auto-generated class with additional functionality. Is it possible?
I have some standard SQLAlchemy models that I reuse across projects. Something like this:
from sqlalchemy import Column, Integer, String, Unicode
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Category(Base):
__tablename__ = 'category'
id = Column(Integer, primary_key=True)
slug = Column(String(250), nullable=False, unique=True)
title = Column(Unicode(250), nullable=False)
def __call__(self):
return self.title
I'd like to put this in a shared library and import it into each new project instead of cutting and pasting it, but I can't, because the declarative_base instance is defined separately in the project. If there's more than one, they won't share sessions. How do I work around this?
Here's another question that suggests using mixin classes. Could that work? Will SQLAlchemy accurately import foreign keys from mixin classes?
When you call
Base = declarative_base()
SA create new metadata for this Base.
To reuse your models you must bind metadata of main models to reusable models, but before any import of your reusable models by:
Base.metadata = my_main_app.db.metadata
MixIn classes useful for repeating column declarations, and extending class methods.
For connecting reusable apps based on MixIns you must define concrete class in code manualy for each model.
Will SQLAlchemy accurately import
foreign keys from mixin classes?
MixIn class with foreign key and constraint
from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.ext.declarative import declared_attr
class MessageMixIn(object):
ttime = Column(DateTime)
#declared_attr
def sometable_id(cls):
return Column(Integer, ForeignKey('sometable.id'))
#declared_attr
def __table_args__(cls):
return (UniqueConstraint('sometable_id', 'ttime'), {})
I have fields created_by and updated_by in each models. These fields are automatically filled with sqlalchemy.event.listen (formerly MapperExtension). For each model, I write:
event.listen(Equipment, 'before_insert', get_created_by_id)
event.listen(Equipment, 'before_update', get_updated_by_id)
When the model was a lot of code gets ugly. Is it possible to apply event.listen immediately to all models or several?
UPD: I'm trying to do so:
import pylons
from sqlalchemy import event, sql
from sqlalchemy import Table, ForeignKey, Column
from sqlalchemy.databases import postgresql
from sqlalchemy.schema import UniqueConstraint, CheckConstraint
from sqlalchemy.types import String, Unicode, UnicodeText, Integer, DateTime,\
Boolean, Float
from sqlalchemy.orm import relation, backref, synonym, relationship
from sqlalchemy import func
from sqlalchemy import desc
from sqlalchemy.orm.exc import NoResultFound
from myapp.model.meta import Session as s
from myapp.model.meta import metadata, DeclarativeBase
from pylons import request
def created_by(mapper, connection, target):
identity = request.environ.get('repoze.who.identity')
if identity:
id = identity['user'].user_id
target.created_by = id
def updated_by(mapper, connection, target):
identity = request.environ.get('repoze.who.identity')
if identity:
id = identity['user'].user_id
target.updated_by = id
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.declarative import has_inherited_table
class TestMixin(DeclarativeBase):
__tablename__ = 'TestMixin'
id = Column(Integer, autoincrement=True, primary_key=True)
event.listen(TestMixin, 'before_insert', created_by)
event.listen(TestMixin, 'before_update', updated_by)
class MyClass(TestMixin):
__tablename__ = 'MyClass'
__mapper_args__ = {'concrete':True}
id = Column(Integer, autoincrement=True, primary_key=True)
created_by = Column(Integer, ForeignKey('user.user_id',
onupdate="cascade", ondelete="restrict"))
updated_by = Column(Integer, ForeignKey('user.user_id',
onupdate="cascade", ondelete="restrict"))
When I add a new MyClass object I have created_by = None. If I create event.listen for MyClass all is fine. What's wrong?
Inherit all your models from the base class and subscribe to that base class:
event.listen(MyBaseMixin, 'before_insert', get_created_by_id, propagate=True)
event.listen(MyBaseMixin, 'before_update', get_updated_by_id, propagate=True)
See more on Mixin and Custom Base Classes
In newer versions of sqlalchemy (1.2+), the following event targets are available:
mapped classes (that is, subscribe to every model)
unmapped superclasses (that is, Base, and mixins, using the propagate=True flag)
Mapper objects
Mapper class itself
So, in order to listen to all instance events, you can listen on Mapper itself:
from typing import Set, Optional
import sqlalchemy as sa
import sqlalchemy.orm.query
import sqlalchemy.event
#sa.event.listens_for(sa.orm.Mapper, 'refresh', named=True)
def on_instance_refresh(target: type,
context: sa.orm.query.QueryContext,
attrs: Optional[Set[str]]):
ssn: sqlalchemy.orm.Session = context.session
print(target, attrs)
this way you will get an app-wide event listener.
If you want to only listen to your own models, use the Base class
I have some standard SQLAlchemy models that I reuse across projects. Something like this:
from sqlalchemy import Column, Integer, String, Unicode
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Category(Base):
__tablename__ = 'category'
id = Column(Integer, primary_key=True)
slug = Column(String(250), nullable=False, unique=True)
title = Column(Unicode(250), nullable=False)
def __call__(self):
return self.title
I'd like to put this in a shared library and import it into each new project instead of cutting and pasting it, but I can't, because the declarative_base instance is defined separately in the project. If there's more than one, they won't share sessions. How do I work around this?
Here's another question that suggests using mixin classes. Could that work? Will SQLAlchemy accurately import foreign keys from mixin classes?
When you call
Base = declarative_base()
SA create new metadata for this Base.
To reuse your models you must bind metadata of main models to reusable models, but before any import of your reusable models by:
Base.metadata = my_main_app.db.metadata
MixIn classes useful for repeating column declarations, and extending class methods.
For connecting reusable apps based on MixIns you must define concrete class in code manualy for each model.
Will SQLAlchemy accurately import
foreign keys from mixin classes?
MixIn class with foreign key and constraint
from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.ext.declarative import declared_attr
class MessageMixIn(object):
ttime = Column(DateTime)
#declared_attr
def sometable_id(cls):
return Column(Integer, ForeignKey('sometable.id'))
#declared_attr
def __table_args__(cls):
return (UniqueConstraint('sometable_id', 'ttime'), {})