Datenbankabfragen

Die Implementierung des IRegistrations-Interfaces aus Hilfsmethoden erfolgt nun in occurrence.py:

from zope.interface import implements
from zope.component import getUtility
from zope.app.component.hooks import getSite

from Products.CMFCore.interfaces import ISiteRoot
from Products.CMFCore.utils import getToolByName

from vs.registration.interfaces import IRegistrant
from vs.registration.interfaces import IRegistration
from vs.registration.interfaces import IOccurrence
from vs.registration.interfaces import IRegistrations

import sqlalchemy as sql
from collective.lead.interfaces import IDatabase

...

class Registrations(object):
    implements(IRegistrations)

    def registrations_for_registrant(self, registrant):
        db = getUtility(IDatabase, name='vs.reservations')
        connection = db.connection

        statement = sql.select([Occurrence.c.registration_key],
                               sql.and_(
                                    Occurrence.c.registrant_key == registrant.registrant_key,
                               ),
                               distinct=True)

        results = connection.execute(statement).fetchall()

        registration_keys = [row['registration_key'] for row in results]

        site = getSite()
        catalog = getToolByName(site, 'portal_catalog')

        return [ dict(registration_key=registration.registration_key,
                      url=registration.getURL(),
                      title=registration.Title,)
                 for registration in
                    catalog(object_provides=IRegistration.__keyentifier__,
                            registration_key=registration_keys,
                            sort_on='sortable_title')
               ]

In der Registrations-Klasse werden Occurrences von Registrants in Registrations gefunden. Dabei wird zunächst die Datenbankverbindung hergestellt. Anschließend werden verschiedene SQLAlchemy-Konstrukte verwendet um eine Datenbankabfrage an der occurrence-Datenbank vorzunehmen. So bedeutet z.B. die Syntax Occurrence.c.registrant_key, dass ein Mapping zwischen der registrant_key-Spalte (c olumn) der occurrence-Tabelle und der Occurrence-Klasse stattfindet. Die Syntax ist umfangreich beschrieben in der SQLAlchemy-Dokumentation. Schließlich wird eine Plone-Katalogabfrage nach registrant-Objekten mit den in der occurrence-Tabelle gefundenen registration_keys erstellt. Diese werden dann in eine Liste von Wörterbuchern, wie sie in IRegistrations definiert sind, gepackt.

Die occurrences-Methode nutzt hingegen SQLAlchemys ORM-API um die Occurrences eines gegebenen Registrant als Liste von Occurrence-Objekten auszugeben:

def occurrences(self, registrant, registration):

    db = getUtility(IDatabase, name='vs.reservations')
    session = db.session

    occurrences = session.query(Occurrence).select(sql.and_(
                                                       Occurrence.c.registrant_key==registrant.registrant_key,
                                                       Occurrence.c.registration_key==registration.registration_key,
                                                       ),
                                                   )

    for occurrence in occurrences:
        occurrence.registrant = registrant
        occurrence.registration = registration

    return occurrences

Da kein Mapping zwischen den Registrant- und Registration-Klassen und der Datenbank stattfindet, können sie von SQLAlchemy nicht geladen und zurückgegeben werden. Stattdessen werden die registrant- und registration-Attribute direkt beim Laden des Objekts gesetzt.