Base de datos SQL y Plone

Existen muchos mecanismos de conexión a base de datos SQL desde Plone CMS, en este articulo se enfoca en la amplia usada librería SQLAlchemy y sus mecanismos de integración.

¿Qué es SQLAlchemy?

SQLAlchemy, es un toolkit de SQL en Python para hacer mapas de objetos relacionales (ORM - Object Relational Mapper) que le permite a los desarrolladores de aplicaciones incorporar toda la potencia e flexibilidad del estándar SQL.

¿Qué son los ZSQL Methods?

Del ingles ZSQL Methods, los métodos ZSQL son un objeto similar a un método DTML de Zope o scripts de Python especializados para su uso con bases de datos relacionales. Son la forma más fácil de conectar RDBMS en Zope. Contiene comando SQL y DTML en combinación.

Productos disponibles en Plone

Existen varios productos disponibles para integrar SQLAlchemy con Plone como se describen a continuación:

En el producto elegido para esta labor es z3c.saconfig a continuación se describe su configuración:

Configuración

  • La configuración de la conexión se realiza en el fichero configure.zcml.
  • Se usan la utilidad global y utilidad local.
  • Pueden ser configuradas como conexiones globales - por una instancia de Zope.
  • O locales para cada sitio Plone.

Configuración ZCML

A continuación un ejemplo del archivo configure.zcml:

<include package="z3c.saconfig" file="meta.zcml"/>
<db:engine name="cliente1_registros"
           url="postgresql://usuario:contrasena@127.0.0.1/db_cliente1_registros?charset=utf8" />
<db:session name="cliente1.registros" engine="cliente1_registros" />

Configuración del paquete

A continuación un ejemplo del archivo config.py:

from sqlalchemy.ext.declarative import declarative_base
from z3c.saconfig import named_scoped_session

Base = declarative_base()
SCOPED_SESSION_NAME = 'cliente1.registros'
session = named_scoped_session(SCOPED_SESSION_NAME)

Interfaces del paquetes

A continuación un ejemplo del archivo interfaces.py:

from zope import interface, schema
from cliente1.registros import MessageFactory as _

class IProject(interface.Interface):
    """Defines Project form interface.
    """
    fullname = schema.TextLine(
        title=_(u'Project name'),
        required=True)

    email = schema.TextLine(
        title=_(u"Project e-mail"),
        required=True)

    type = schema.Choice(
        title=_(u'Category'),
        vocabulary=vocabulary.member_types,
        default='profissional',
        description=_(u'''Please select a project category.'''),
        required=True)

    status = schema.TextLine(
        title=_(u'Project status'),
        required=True)

    created_date = schema.TextLine(
        title=_(u'Project created date'),
        required=True)

    organization = schema.TextLine(
        title=_(u'Organization'),
        description=_(u'Please advise which organization '\
            'you belong. eg company, university or entity.'),
        required=False)

Mapeo objeto-relacional de la tabla

A continuación un ejemplo del archivo models.py:

import datetime
import sqlalchemy as sa

from cliente1.registros.config import Base

class Project(Base):
    """A project"""

    implements(IProject)
    __tablename__ = 'project'

    id = Column(sa.Integer,nullable=False,index=True,primary_key=True)
    fullname = Column(sa.String(64))
    email = Column(sa.String(64), unique=True)
    type = Column(sa.String(64))
    status = Column(sa.String(64), default='pending')
    created_date = Column(sa.DateTime, default=datetime.datetime.now())
    organization = Column(sa.String(255))

Formulario CRUD

El objetivo general de z3c.form y hacer que el desarrollo de formularios lo más simples posible, mientras que proporciona hooks para permitir la personalización de los formularios en cualquier nivel de acuerdo a las necesidades reales de los diferentes casos de uso.

Los principales componentes (módulos):

form
formularios base: Form, AddForm, EditForm, DisplayForm
groups
formularios compuestos de los grupos de campos (fieldsets)
subform
formularios anidados
field
API para manipulación de los campos del formulario
button
API para manipulación de los botones del formulario
validator
API para la validación de los datos del formulario
widget
API para la creación de los widgets
action
API para definición e manipulación de actions handlers

procesamiento del formulario

A continuación los elementos principales del procesamiento del formulario:

self.request
objeto que representa la actual solicitud HTTP
self.context
Elemento relacionado al formulario según el contexto en el que se invoca;
self.getContent()
Los objetos sacados de contexto y que serán manejado por el formulario, a menos ignoreContext se establece en True;
self.status
El mensaje se mostrará en la parte superior de la región de Contenido cuando el formulario se representa.
updateWidgets
actualizaciones de todos los widgets de acuerdo a los datos enviados.
updateActions
invoca los actions handlers del formulario de acuerdo con el botón presionado
render
invoca la plantilla Padre que genera el formulario HTML y devuelve dicho contenido

Creación de la base de datos

Para esto se usa la receta zc.buildout llamada collective.recipe.pgcreatedb el cual crea una base de datos Postgresql a través de SQLAlchemy, a continuación ejemplo de su configuración:

[buildout]
parts =
    ...
    rdbs-requeriments
    rdbs-createdb
...
# This recipe helps to install Postgresql pre-requeriments
# For options see http://pypi.python.org/pypi/plone.recipe.command
[rdbs-requeriments]
recipe = plone.recipe.command
command =
    sudo aptitude install -y postgresql postgresql-server-dev-all libpq-dev phppgadmin
stop-on-error = false
update-command = ${rdbs-requeriments:command}
...
# This recipe helps to create a database Postgresql with SQLAlchemy
# For options see https://svn.plone.org/svn/collective/collective.recipe.pgcreatedb/trunk
[rdbs-createdb]
recipe = collective.recipe.pgcreatedb
default-template = template1
user = postgres
password = postgres
database = db_cliente1_registros
host = 127.0.0.1
create-tables = off
eggs = ${instance:eggs}
extra-paths  =  ${buildout:parts-directory}/
...

En la sección buildout llamada rdbs-requeriments instala el servidor postgresql con sus librerías de desarrollo y adicionalmente instala phppgadmin para la gestión remota del mismo.

En la sección buildout llamada rdbs-createdb crea crea una base de datos Postgresql a través de SQLAlchemy.

Creación de las tablas

A continuación se demuestra un ejemplo del archivo import_steps.xml para la creación de las tablas:

Perfil de importación Generic Setup

  • La creación de las tablas se lleva a cabo al disparar el perfil de importación del producto.
  • El archivo import_steps.xml.
<?xml version="1.0"?>
<import-steps>
    <import-step id="identificador-create_tables" version="20101020-11"
                 handler="cliente1.registros.setuphandlers.create_tables"
                 title="Create Base Tables">
        <dependency step="toolset" />
    </import-step>
</import-steps>

Lanzador del perfil de importación

A continuación un ejemplo del archivo setuphandlers.py:

from z3c.saconfig import named_scoped_session
from cliente1.registros.config import Base
from cliente1.registros.config import SCOPED_SESSION_NAME

Session = named_scoped_session(SCOPED_SESSION_NAME)

class create_tables(context):
    '''Called at profile import time to create necessary tables'''

    if isNotOurProfile(context):
        return

    Base.metadata.create_all(bind=Session.bind)
los comentarios son proporcionados por Disqus

Editar este documento

El código fuente de este archivo esta hospedado en GitHub. Todos pueden actualizar y corregir errores en este documento con unos clic - sin necesidad de descargar.

  1. Vaya hacia el articulo Base de datos SQL y Plone en GitHub.
  2. Presione el botón Fork. Este creara su propia copia personal de la documentación.
  3. Edite los archivos usando el editor de texto de GitHub desde su navegador Web
  4. Rellene en la caja de texto Commit message al final de la pagina indicando por que usted realizo estos cambios. Presione el botón Propose file change próximo a ese cuando haya finalizado.
  5. Luego diríjase a la página Send a pull request (no será necesario rellenar ningún texto adicional). Sólo tiene que pulsar el botón Send pull request.
  6. Sus cambios serán consultados por un revisor dentro de la pestaña Pull requests del proyecto en Github.

Para mas información básica acerca de como actualizar este manual y referencia a sintaxis Sphinx, por favor consulte la guía Escribiendo y actualizando el manual.