On 02/04/2013 11:30 AM, Michael Bayer wrote:
> 
> On Feb 4, 2013, at 1:04 AM, ru...@yahoo.com <mailto:ru...@yahoo.com>
> 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 sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to