a view looks just like a table to SQLAlchemy. the only thing that might
not work is reflecting it. otherwise you can just pretend its a Table
(just can't flush to it).
allen.fowler wrote:
...
> To clarify:
>
> I am using SQLAlchemy's Declarative Base to fully define and create my
> database.
>
> For instance, there is a simple class/table Records, and I would like
> to define a class CurrentRecords that is implemented in the database
> as a view on Records.
>
> In this way, I can avoid polluting my application code with filtering
> out all the non-active records every time I want to query Records.
>
Just define CurrentRecords as a table, i.e. in my app one of my views is:
class Vconsumption(Base):
__table__ = sa.Table(u'vconsumption', metadata,
sa.Column(u'consumptionid', sa.Integer(),
sa.ForeignKey(u'consumption.consumptionid'), primary_key=True),
...
)
consumption = sao.relation(Consumption)
And I relate it back to the real consumption table, but never
write/flush the view and do have to have a unique key which you define
as "primary key" to SA.
Werner
Yes - SA's ORM can map to arbitrary Selectable object. Selectable is
the base class for things like select() in SA. This feature is
awesome! Rather than specifying your Table object to orm.mapper,
specify a Selectable that returns rows that are what you want to see.
--
Ross Vandegrift
ro...@kallisti.us
"If the fight gets hot, the songs get hotter. If the going gets tough,
the songs get tougher."
--Woody Guthrie
> So, just to clarify:
>
> At this point in time, can SQLAlchemy be used to define and query
> simple VIEWs in a database agnostic manner?
>
> And if not, is this a feature that is slated for addition any time
> soon?
CREATE VIEW is almost identical across backends and can be achieved
like this:
someselect = select([table.c.foo, table.c.bar])
eng = create_engine('...')
eng.execute("CREATE VIEW foobar AS %s" % someselect.compile(eng))
then build yourself a Table with columns representing the view.
its easy enough to build a CreateView DDL() construct in 0.6 to do
this, i.e.
eng.execute(CreateView("myview", someselect))
I'd consult the sqlalchemy.ext.compiler docs for how to do this.
as a builtin I'm uncomfortable since it implies adding a View() object
to schema which raises lots of thorny questions like "what if I
construct an INSERT against the view ?" " what about materialized
views?" , "what if I join my View() to the underlying Table() ?" etc.
>
>
> Still, though, it looses the auto generation capability via
> drop_all()/
> create_all() vs. traditional tables and feels out-of-place along side
> the rest of SQLAlchemy's slickness.
I still have the job of documenting 0.6's features, but even in 0.5
any DDL() construct can be associated with MetaData as an event (this
is in the 0.5 API docs). This can all be done in 0.5 using just
DDL(), 0.6 will just provide a straighter user-definable path right
through the entirety of SQLAs entire DDL generation process.
> I do understand your concern about adding a View() object at this
> stage. Perhaps it could be implemented by limiting it's scope and
> thinking of a better word to describe what is needed since it is not a
> VIEW in the full meaning of the word. (SimpleView? PreSelected?)
All of the edge cases are what come about once I put the whole thing
in core, and people start turning the crank further and further,
expecting to see what "they expect" and then complaining when it
doesn't work (i.e. they cease to be alchemists!). As a usage recipe,
users assume responsibility for the limitations of the approach as
well as its mechanisms.
So here is that recipe: http://www.sqlalchemy.org/trac/wiki/UsageRecipes/Views
. its 20 lines of public API save for one underscore method which I
suppose we can make public (its just hard to explain, mostly). I
think you'll see its pretty clean as a user recipe.