==================== Datenbankanbindungen ==================== SQLAlchemy bietet standardisierte Interaktionsmuster zur Erstellung von Engines, Metadata, Tabellen und Mapper. Dabei ist zu beachten, dass - verschiedene Produkte ihre eigenen Datenbankverbindungen aufbauen; - jede geteilte Datenbankquelle *thread-safe* ist; - Datenbanktransaktionen mit Zope-Transaktionen synchronisiert werden; - *Data Source names* (DSN) zur Laufzeit nicht bekannt sind. `collective.lead`_ bietet eine Basisklasse zur Erstellung von Hilfsmethoden, die Verbindungseinstellungen, Tabellen und Mapper kapseln. Damit wir dies in unseren Hilfsmethoden ``vs.registrations`` und ``vs.reservations`` verwenden können, wird ``collective.lead`` als Abhängigkeit in ``vs.registration/setup.py`` eingetragen:: install_requires=[ 'setuptools', # -*- Extra requirements: -*- 'MySQL-python', 'collective.lead>=1.0b3,<2.0dev', ], Bei einem Aufruf von ``./bin/buildout`` sollte nun ``collective.lead`` mitinstalliert werden, welches dann die letzte unterstützte Version von SQLAlchemy installiert. Daneben benötigen wir noch das MySQL-python-Paket, welches MySQL-Treiber für Python bereitstellt. Das Datenbank-Hilfsprogramm selbst wird dann in ``vs.registration/vs/registration/db.py`` erstellt. Die Datei enthält ebenfalls die Implementierung von ``IDatabaseSettings``, eine persistente, lokale Hilfsmethode zum Speichern der Verbindungseinstellungen:: from persistent import Persistent from zope.interface import implements from zope.component import getUtility from collective.lead import Database from vs.registration.interfaces import IDatabaseSettings from sqlalchemy.engine.url import URL from sqlalchemy import Table, mapper, relation from vs.registration.occurrence import Occurrence from vs.registration.reservation import Reservation class ReservationsDatabaseSettings(Persistent): implements(IDatabaseSettings) drivername = 'mysql' hostname = 'localhost' port = None username = '' password = None database = '' class ReservationsDatabase(Database): @property def _url(self): settings = getUtility(IDatabaseSettings) return URL(drivername=settings.drivername, username=settings.username, password=settings.password, host=settings.hostname, port=settings.port, database=settings.database) def _setup_tables(self, metadata, tables): tables['occurrence'] = Table('occurrence', metadata, autoload=True) tables['reservation'] = Table('reservation', metadata, autoload=True) def _setup_mappers(self, tables, mappers): mappers['occurrence'] = mapper(Occurrence, tables['occurrence']) mappers['reservation'] = mapper(Reservation, tables['reservation'], properties = { 'occurrence' : relation(Occurrence), }) Die ``collective.lead.Database``-Klasse erlaubt uns, nur wenige Eigenschaften anzugeben, um eine Datenbankverbindung, Tabellen und Mapper zu erstellen. Nun wird die ``ReservationsDatabase``-Methode noch in ``vs.registration/vs/registration/configure.zcml`` registriert:: Da die lokale ``ReservationsDatabaseSettings``-Hilfsmethode jedoch erst mit der Installation des Produkts registriert werden muss, kann das Generic Setup-Profil ``vs.registration/vs/registration/profiles/default/componentregistry.xml`` hierfür verwendet werden:: Nun sollte auf die Datenbank zugegriffen werden können mit:: >>> from zope.component import getUtility >>> from collective.lead.interfaces import IDatabase >>> db = getUtility(IDatabase, name='vs.reservations') Dem ``db``-Objekt stehen anschließend die Eigenschaften von ``collective.lead.interfaces.IDatabase`` zur Verfügung. .. _`collective.lead`: https://svn.plone.org/svn/collective/collective.lead