Martijn Faassen showed a grok + sqlalchemy application he's been working on. This got everyone into the spirit and more importantly into the problem domain. Something he used a lot was custom traversal to navigate the relational database model with URLs. With some quick pseudocode:
from zope.location.location import located class Something(grok.Model): def traverse(self.name): item = session.query(...).first() # or .one() if item == None: return return located(item)
Storm is an alternative to sqlalchemy. Storm seems to be oriented more towards the needs of big complex projects. Sqlalchemy seems much more active open source community-wise. Storm is less "friendly" as you have to / can configure everything, just like zope3. Sqlalchemy seems more grok-like in outlook. At least, that's what I extracted from the discussion.
An outcome of the discussion was that grok needs a to make it real easy to
traverse to attributes. Unrelated to, but useful for, relational db
integration. grok.traversable("something")
was suggested. So this is in
addition to the normal container traversal which effectively works with
dictionary access (container["subitem_id"]
). A shorthand that prevents you
from having to write your own traverse() method in many common cases: so very
grok-like.
A useful warning came up in the discussion. In zope, it is really easy to see everything as folders. In sql, you're making it all relational. Both are not 100% right object-oriented wise. Watch out for brainwashing based on your environment.
We went through the zope api docs for zope.app.container, writing down which sqlalchemy information we ought to use for treating the mapped sqlalchemy results as a container. This helped us to flush out some corner cases.
An essential point is to use sqlalchemy and its ORM mapper for the things that that is good at. As grok we won't do the sqlalchemy work, we'll just provide extra grok-specific functionality like traversal and folderish behaviour. Folderish behaviour means, as an example, in handling a "delete" correctly. Correctness is should be handled on the sqlalchemy level: if you configure your mapper right, the right thing will happen. That might sound dead-pan but it is, actually.
Grok also means: "not invented here: in a positive way". What other people figured out and did right is what we don't have to re-invent. So we won't invent it here.
Something that we'd need to figure out: how and where to define the classes, tables and mappers? Do we want it all easily in one class? Do we need to grok something?
Grok needs the fields for the add and edit forms. We didn't like defining an interface for the fields as that's partially double, partially potentially late-binding, etc. So something simple like:
def form_fields(self): return grok.Fields(rdb.Schema(OurClass))
There was much more, but this ought to do for a summary. I didn't contribute much myself (especially since I have basically no grok experience!). I did learn a lot by listening, picking up useful concepts and ways of working. Nice sprint till now!
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):