On Feb 5, 2013, at 1:19 PM, [email protected] wrote: > > 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'])
that's classical mapping. > > 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. i think you're referring to the usage of reflection. Declarative works with this just as, if not more, nicely. the declarative style only means that a class and the fact that it is mapped to a database table are defined at once. > 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. but already, the Oreilly book has led you into an antiquated usage pattern. Reflecting with declarative works typically as: Base = declarative_base(cls=DeferredReflection) class MyClass(Base): __tablename__ = 'mytable' Base.prepare(some_engine) this is documented at "Using Reflection with Declarative": http://docs.sqlalchemy.org/en/rel_0_8/orm/extensions/declarative.html#using-reflection-with-declarative However, I will note that for application design, while I certainly agree that a SQL schema should be designed separately from a domain model, I still find it best that the system of generating the schema be done in Python code and not as literal SQL scripts. This also allows migration tools such as Alembic to be used effectively. This is not the same thing as the schema being designed specific to one application, just that Python tools are used to automate the task of creating and maintaining changes to a schema. What I would likely do if i really wanted a schema totally built prior to an application would be to use a system of Table metadata to define and generate the schema, in conjunction with Alembic to maintain changes, I'd then have that system of Table metadata available as a dependency to other applications that wish to build upon it (i.e. class MyClass(Base): __table__ = mymodel.tables.some_table) , thus bypassing the expensive and sometimes error prone reflection process. Reflection is only something I use when I'm writing a small app to talk to some existing system like a Wordpress database (though people certainly use it as you are for substantial applications). > > 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)" Yes, that content is entirely derived from our first tutorial, not quite verbatim but almost. At some point, the declarative example was added after it, as a "defining everything all at once" option, and later, we went full on with "only one way to do it" and just removed the classical mapping version totally. Classical mapping is a more basic, less capable system and there's not much reason for people to use it unless they really are sticklers for absolute separation of domain model and persistence, however, this isn't really even possible since applying mapper() to a class significantly changes the behavior of the class in any case. Therefore while all options remain to keep Table metadata separate, i think it's an outdated approach to separate mapper() from class. Users most significantly want usage patterns and best practices to be documented above all else, so the documentation has been evolving to stress recommended patterns over nuts and bolts, which people really aren't very interested in. > > 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. Just to review, mapping is first introduced in the tutorial when one reads the section called "Declare a Mapping": http://docs.sqlalchemy.org/en/rel_0_8/orm/tutorial.html#declare-a-mapping i know this is not the case for you, but for the vast majority of users, they just want to get on with some code examples showing the absolute best way to do something. A description of this length is more than enough for most users and if it were to be four or five paragraphs longer, users would generally be overwhelmed, skip it, or just generally be more intimidated overall, as this is only the tutorial and is geared towards new users. A detailed exposition of "what it means to map" is not what most users wish to see here. What they wish to see by an overwhelming margin are concrete examples of fully integrated applications as well as deep discussion of best practices (most of which involves the Session. The Session is really by far where people have the most issues with our docs so most of the attention has gone there). Removing classical mapping from the tutorial was part of the move towards a more streamlined and less meandering document that attempts to steer users into best practices without confusing them (yet the tweets continue: https://twitter.com/lawouach/status/298446980835852288 ) For those who really want to know what a "mapping" is, they are first encouraged to read "Classical Mappings", which talks all about mapper(): http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=classical%20mappings#classical-mappings paragraphs can be added here since this is outside of the tutorial and is more of an optional read. More detail about mapping then comes from the docstrings: http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=classical%20mappings#sqlalchemy.orm.mapper and http://docs.sqlalchemy.org/en/rel_0_8/orm/mapper_config.html?highlight=classical%20mappings#sqlalchemy.orm.mapper.Mapper. We then have a glossary: http://docs.sqlalchemy.org/en/rel_0_8/glossary.html. This area also has a description of "mapper", which is far too short right now, but this is where a lot of detail could be provided. We would invite documentation contributors to feel free to provide any number of paragraphs to be placed there. > 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. Continuing on, those who have a large appetite for the specific and the technical, while still remaining in prose format, can read my chapter in the "Architecture of Open Source Applications" on SQLAlchemy http://www.aosabook.org/en/sqlalchemy.html where you can read all about this detailed architectural diagram http://www.aosabook.org/images/sqlalchemy/mapper-components.png . I think it's fairly obvious that a diagram of this nature is overkill for the vast majority of new users to be exposed to, as it is entirely unnecessary understanding basic ORM usage. Also note I have been under contract for seven years by Prentice to produce a new, definitive SQLAlchemy book. I've have always been in search of co-authors but haven't gotten anyone to actually produce any content. There's no money in books and to write one for this library would require many hundreds of highly focused hours. > 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 I hope it's clear at this point where we would welcome the contribution of many new paragraphs regarding the meaning and specifics of mapping. > > 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. the part that you're praising was essentially a rehash of my original writing, so complement accepted :). I really don't want to encourage people to use classical mappings. > 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. contributions are the best way to crystallize one's sense of where the docs should be going. > > >>>> 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) So did I, back when I added all that logging years ago. But nobody ever used it, and I also noted that *I* never used it either, as it was simultaneously too verbose and not specific enough. When i need to trace what a mapping is doing, I use pdb. For those who aren't familiar with mapper internals, they do nothing, you can't really do much with mapper logging unless you're fairly well familiar with the internals. > but a) I can't seem to get any output from the debug level > orm logger the ORM doesn't do any debug level logging these days, it adds to much verbosity and performance overhead to the code and nobody used it. > and b) perhaps the engine's sql output is really > all I need to see. for getting an app to run efficiently, it pretty much is. It's all I need even when debugging complex issues. > 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. I'll accept a patch for a few lines under the mapping.rst document, as well as cross linkage from the engine.rst section talking about logging. > > 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?) that flag is gone so if it's still in an .rst document that's a bug. -- 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.
