On 02/04/2013 11:30 AM, Michael Bayer wrote:
>
> On Feb 4, 2013, at 1:04 AM, [email protected] <mailto:[email protected]>
> wrote:
>
>> simply didn't get from the docs. Like the fact that I could create
>> a mapped object simply with
>>
>> class User: pass
>>
>> rather than explicitly specifying all the attributes. Without that
>> I wouldn't even be trying to use sqlalchemy today.
>
> Well, the majority of users who see "class User" and then the
> separate "mapper()" + "Table" step, which for many years was how we
> documented it, would lead new users to say, "what! that's so verbose!
> I'm going back to Django where I can define everything inline". So
> a lot more people weren't trying to use us on that side of things :)
> Also, I personally found class + mapper() + Table to be unworkable in
> practice - declarative offers all kinds of advantages over the plain
> approach and greatly reduces boilerplate and redundancy. Often I
> will keep the Table metadata explicit but just define it within the
> declarative class as such:
>
> class SomeClass(Base): __table__ = Table('sometable', Base.metadata,
> Column(...), ... )
>
> that style is documented at
>
http://docs.sqlalchemy.org/en/rel_0_8/orm/extensions/declarative.html#using-a-hybrid-approach-with-table
Actually I did not mean either declarative or classical
mapping, I meant whatever style this is called:
class User: pass
class Address: pass
engine = sa.create_engine (connectstr)
connection = engine.connect()
meta = sa.MetaData()
meta.reflect (bind=engine)
sa.orm.mapper (User, meta.tables['user'],
properties={'addresses':
sa.orm.relationship (Address, ...)}
sa.orm.mapper (Addresses, meta.tables['addresses'])
In contrast to what I call "app-centric" code (in which the
database is subservient to and exists to provide persistent
storage services for the app, and in which it is perfectly
natural to define and create the database schema from
within the app code), nearly all my code is what I call
"data-centric": that is, the data are the family jewels and
exist both before and long after any particular app comes
along.
For this kind of app, the database schema and data integrity
constraints are (and always will be) defined in sql, outside
of any app. What I don't want to have to do is maintain a
second copy of basically the same information in the app's
python code (in either classical or declarative form), hence
my joy at finding sqlalchemy's reflect() coupled with sqlalchemy's
ability to map a bare, skeleton user class; it adds the regular
column attributes without needing them specified and all I have
to do is tell it what FK relationships I want manifested as
extra attributes.
I realize both these capabilities are documented -- but when
I read the docs, although I found and figured out how to use
reflect(), I did not see any way to define classes that did
not involve explicitly listing all their columns and other
stuff already defined in my sql schema scripts) until I got
Copeland's book.
> The ORM tutorial is really quite carefully written, to make sure
> people are at least somewhat aware, as they are seeing SQLAlchemy ORM
> usage for the first time, that they are building upon a system that
> can be broken into smaller parts:
>
> With our User class constructed via the Declarative system, we have
> defined information about our table, known as *table metadata*, as
> well as a user-defined class which is linked to this table, known as
> a *mapped class*. Declarative has provided for us a shorthand system
> for what in SQLAlchemy is called a “Classical Mapping”, which
> specifies these two units separately and is discussed in /Classical
> Mappings/
>
<http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html#classical-mapping>.
> The table is actually represented by a datastructure known as Table
>
<http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html#sqlalchemy.schema.Table>,
> and the mapping represented by a Mapper
>
<http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html#sqlalchemy.orm.mapper.Mapper>
> object generated by a function called mapper()
>
<http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html#sqlalchemy.orm.mapper>.
> Declarative performs both of these steps for us, making available the
> Table
>
<http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html#sqlalchemy.schema.Table>
> it has created via the __table__ attribute:
>
> "Classical mappings" is linked, you go there, and see the
> traditional mapping, a plain User class with nothing but a
> constructor. The constructor is not needed and at the moment this
> appears to not be mentioned.
Ah, I see it now, you're talking about the second grey
example box, yes? Even with your direction, I missed that
on the first couple of scans of that page -- I think because
of the presence of the table definitions and of the similar
looking initializers in the User class.
If that example (with no verbiage, and read after miles of
tutorial examples that explicitly define columns) is what
should have told me I do not need explicit column attributes,
I think I should be forgiven for missing it.
Compare with Copeland, page 3:
"Using the ORM is as simple as writing your classes, defining
your tables, and mapping your tables to your classes. In the
case of the user table you could perform a simple mapping via
the following code:
class User (object): pass
mapper (User, user_table)"
What's missing in the sqlalchemy docs for me is a basic
explanation of what "mapping" is and what a mapper does.
I would expect such an explanation in the Overview but that
section is almost empty.
The tutorial says a mapper is
"a method of associating user-defined Python classes with
database tables, and instances of those classes (objects)
with rows in their corresponding tables."
which is true as far as it goes but "associates" is pretty
vague. Associates how? To a new user like me that is
pretty meaningless.
Eventually, after more reading and working backwards
from the tutorial examples one realizes it means roughly,
modifying a class by adding attributes to it corresponding
to the columns of a table. Of course there is more to it
than that, but that fundamental idea is at the core and
should be established very early.
I think if those first few paragraphs of the tutorial were
expanded, used more concrete python and database terminology
(as opposed the more abstract and sqlalchemy-specific terms
used throughout the rest of the docs), supplemented with
expository (rather than runnable tutorial-style) examples
and moved from the Tutorial to the Overview section, it would
help new users form a clearer mental model of what the orm
does which would make understanding the following material
(both tutorial and reference) easier.
Two last points...
I am *not* praising Copeland's book particularly -- only
saying on the issue of what a mapper does, for a user without
prior orm experience, he is clearer (IMO). In many other
areas he is as opaque as the sqlalchemy docs.
Second, repeating what I said before, I recognize and
appreciate that a lot of work went into the docs so I
hope you'll take these comments as a constructive attempt
to contribute to their continuing improvement and not
just pissing and moaning.
>>>> logging is fully described here:
>>>>
>>>>
http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#configuring-logging
>>
>> Thanks. Since logging applies to other parts of Sqlalchemy besides
>> the engine, would it be better if this were in it own section?
>> Even if not, I think it would help if logging had a link in the
>> table of contents page (http://docs.sqlalchemy.org/en/rel_0_8/)
>
> logging is really about the "Engine" and the "Pool", which is closely
> tied to the Engine. Logging for other areas is being de-emphasized
> as it isn't generally used.
I thought the orm or unitofwork logger might be useful
in understanding what sqlalchemy is doing (and when)
but a) I can't seem to get any output from the debug level
orm logger and b) perhaps the engine's sql output is really
all I need to see. Still, if one sees
logging.getLogger ('sqlalchemy.orm')
in some code and wants to know what it does, looking in
the Engine docs is not the first place that would occur
to me.
FYI, the current logging docs still refer to "the echo_uow
flag used on Session" which seems not to be documented in
the session docs (or even exist anymore?)
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.