On Sun, Jan 31, 2010 at 4:09 AM, Haron Media <[email protected]> wrote: > > I wonder how you build your models, do they handle all the data logic? > > > Porting myself to Python/Pylons, I have to learn to use SQLAlchemy > properly because looking through the 300+ pages of its documentation it > seems complex but very powerful, especially its ORM. > > However in my PHP apps I always contain all the data logic to the model > itself. The controllers only call specific methods in order to do > something with the model, not the data directly: loadById() would load > model data into its properties from relevant tables. save() would check > if pkey is set, and then insert or update existing rows accordingly.
There are several philosophies on this. MVC has strayed far from its original meaning, and there are several equally valid interpretations of it. There are three ways to implement the model. The minimal approach is to put only the table definitions in it. The maximal approach is to put all data logic into it. The super-maximal approach is to write a model abstraction layer, so that you can replace the storage backend completely (e.g., SQLAlchemy to object database or CouchDB). The fourth approach is to put as much logic and permissions checking into the database itself, which is especially feasable with PostgreSQL. One way to say it is that the model is for things specific to your business, the view is for things specific to the UI, and the controller is for things specific to Pylons (the request/response/session API). But some people are more pragmatic, and pull things into the controller that are more easily done in Python code. Because Pylons doesn't have a place for "model logic" and "view logic". Clearly, the model can be separated into logic vs data structure, and the view also contains Python code vs template. That would argue for the model to "contain" the database structure rather than being the database structure, and the view would be a Python function that invokes a template, rather than just the template itself. But Pylons tutorials have always gone for a minimal model and minimal view, and so that's what most people write. I prefer a medium model. I have class methods in my ORM objects for all the logical collections of records my app requires. So one method to iterate the recent records for the home page. Another to do a search. Another to iterate all reacords, But I don't resolve queries into lists. I return the query object so that the controller or template can iterate it, get a record count, etc. That means the controller/template knows it's a SQLAlchemy query, which violates some containment principles, but it leads to the most streamlined code. There are a few people who have been pushing most of their logic into PostgreSQL stored procedures and triggers, and using its roles to enforce permissions. Aruynn Shaw has done the most work on this that I've seen, but last I looked it hadn't gotten onto PyPI and was hard to find. This looks like the best link: https://projects.commandprompt.com/public/ - Exceptable: convert PostgreSQL exceptions to Python exceptions. - Simpycity: a Python db layer for calling PostgreSQL stored procedures. (Not compatible with SQLAlchemy.) - VerticallyChallenged: authorization via database roles, with Repoze.who for authentication. (This one doesn't seem to be online yet.) If you want to use these and reach a dead end, let me know and I can put you in touch with Aurynn. Maybe that will help prod her to make PyPI releases. :) > The problem with that is that the DB engine throws a generic Constraint > Violation from which I have to "extract" constraint name, and produce a > meaningful message to the user, like "Name already exists, please try > another". Therefore I catch generic SQL exceptions in the model save() > method, and re-throw custom exceptions made for the model like, for > example, NameDuplicateError, or EmailDuplicateError, etc... so the > controller can catch these and send back proper message, or alter the > form to highlight fields in question. That's what Exceptable is for. I think it could be made more pythonic, but I haven't had a need for it myself so I haven't had an incentive to. -- Mike Orr <[email protected]> -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
