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.


Reply via email to