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.