Como empezar a desarrollar modulos en OpenERP (2/2)

La arquitectura MVC (Modelo Vista Controlador) sirve para separar los datos, de la lógica de negocio y de la interfaz de usuario, OpenERP sigue esta arquitectura, el modelo son las tablas de postgres, la vista son los XML que definen la interfaz de usuario del módulo y el Controlador son los Objetos creados en python. En esta entrada vamos a ver la estructura de los módulos y como crear un primer módulo muy sencillo.

Lo primero que necesitamos saber es donde se almacenan los módulos y la estructura que tienen. Si estas ejecutando el servidor de OpenERP como he indicado en el post anterior los módulos se almacenan en el directorio:
/home/usuario/openerp/openerp-server/bin/addons

Podemos crear en este directorio la carpeta para nuestro módulo, dentro de la carpeta del modulo se guardan los ficheros del código, tanto los fuentes escritos en python, las vistas en xml, los informes… en este ejemplo vamos a empezar a hacer un módulo muy simple y luego iremos añadiendo cosas. Los archivos mínimos para este módulo de ejemplo son los siguientes:

  • __init__.py
  • __terp__.py
  • coche.py
  • coche_view.xml

Como los módulos de OpenERP son paquetes python tiene que existir el fichero __init__.py que puede definir atributos y métodos del paquete, en este caso solo contendrá los import de los ficheros y directorios que contengan código. En nuestro ejemplo es simplemente:
import coche

El fichero __terp__.py contiene la descripción del modulo:
{
"name" : "coche",
"author" : "Angel",
"version" : "0.1",
"depends" : ["base"],
#esta es la lista de los módulos de los que depende
"init_xml" : [],
"update_xml" : ["coche_view.xml"], #aquí indicamos la vista
"category" : "Enterprise Specific Modules/Coches",
"active": False,
"installable": True
}

En coche.py tenemos tanto el controlador como el modelo, tenemos el controlador porque se trata de una clase python en la que definimos el comportamiento, y tenemos el módelo porque esta clase hereda de la clase osv (Object Service) que implementa una capa de ORM (Object-Relational mapping), para los que venimos de java lo que sería hibernate. Así las clases que creamos heredando de osv y siguiendo esta estructura crean las tablas en la base de datos.

from osv import osv, fields
class coche(osv.osv):
_name = 'coche'
_columns = {
'modelo': fields.char('Modelo', size=64),
'matricula': fields.char('Matricula', size=64),
}
coche()

Como vemos importamos osv para que coche herede de el, e importamos también fields para definir el tipo de las columnas, en este ejemplo solo hemos usado cadenas de caracteres, ya veremos mas tipos de columnas.

El último fichero de nuestro ejemplo es coche_view.xml, en el se define la vista, en este ejemplo se ha creado la entrada para el menú y la definición de la ventana listado y formulario.

<openerp>
<data>
   <record model="ir.actions.act_window" id="action_coche_form">
      <field name="res_model">coche</field>
      <field name="domain">[]</field>
   </record>
   
   <menuitem name="Coches" id="menu_coche_coche_form"/>
   
   <menuitem name="Coches" id="menu_coche_form" parent="coche.menu_coche_coche_form" action="action_coche_form"/>
   <record model="ir.ui.view" id="view_coche_form">
      <field name="name">coche</field>
      <field name="model">coche</field>
      <field name="type">form</field>
      <field name="priority" eval="5"/>
      <field name="arch" type="xml">
         <form string="Coche">
            <field name="modelo" select="1"/>
            <field name="matricula" select="1" />
         </form>
      </field>
   </record>
   <record model="ir.ui.view" id="view_coche_tree">
      <field name="name">coche</field>
      <field name="model">coche</field>
      <field name="type">tree</field>
      <field name="priority" eval="5"/>
      <field name="arch" type="xml">
         <tree string="Coche">
            <field name="modelo" select="1"/>
            <field name="matricula" select="1" />
         </tree>
      </field>
   </record>
</data>
</openerp>

Una vez tenemos este código en el directorio /openerp-server/bin/addons/coche podemos reiniciar openerp-server con la opción “-u coche” para recargar el módulo.

Este ejemplo es un módulo muy sencillo que simplemente permite gestionar en OpenERP una lista de matriculas y modelos de coches, en siguientes post iré ampliando este módulo y mostrando otras características del desarrollo.

Para profundizar mas en el desarrollo ahora que tenemos una base puedes mirar el developer book de la wiki y el memento que resume todo lo necesario para desarrollar en OpenERP.

14 comentarios sobre “Como empezar a desarrollar modulos en OpenERP (2/2)

  1. Lilia González

    Lo primero de todo enhorabuena por tu post, es claro y sencillo, y me ha venido muy bien para empezar a desarrollar módulos.

    Al probar tu código me ha dado un error y es que creo que esta línea es incorrecta “” ya que si pones “parent=coche.menu_coche_coche_form” no funciona. Yo lo he cambiado por “parent=menu_coche_coche_form” y va de perlas.

    Saludos

  2. Angel Moya Autor del artículo

    Muchas gracias, lo tendré en cuenta para revisarlo… como se suele decir en estos casos “en mi casa funcionaba” 😉

  3. Luis Sanhueza

    A mi me falla con Open ERP 6;

    File “/usr/share/pyshared/openerp-server/addons/coche/__init__.py”, line 1, in
    import coche
    File “/usr/share/pyshared/openerp-server/addons/coche/coche.py”, line 3
    _name = ‘coche’
    ^
    IndentationError: expected an indented block

    Saludos.

  4. Angel Moya Autor del artículo

    Hola, tiene toda la pinta de ser un problema de copy/paste…
    En python no hay llaves ( { } ) para cerrar el código, y para estructurarlo es obligatorio tabularlo. Si has copiado el código de la web puede que no este bien tabulado.

  5. Luis Sanhueza

    Efectivamente era problema de tabulacion, lo corregui y paso bien, pero ahora me dio este mensaje:

    File “lxml.etree.pyx”, line 2692, in lxml.etree.parse (src/lxml/lxml.etree.c:49594)
    File “parser.pxi”, line 1522, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:71582)
    File “parser.pxi”, line 1552, in lxml.etree._parseFilelikeDocument (src/lxml/lxml.etree.c:71892)
    File “parser.pxi”, line 1435, in lxml.etree._parseDocFromFilelike (src/lxml/lxml.etree.c:70807)
    File “parser.pxi”, line 997, in lxml.etree._BaseParser._parseDocFromFilelike (src/lxml/lxml.etree.c:67948)
    File “parser.pxi”, line 539, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:63824)
    File “parser.pxi”, line 625, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:64745)
    File “parser.pxi”, line 565, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:64088)
    XMLSyntaxError: Start tag expected, ‘<' not found, line 1, column 1

    Que podra ser?, saludos y gracias por tu ayuda, es un gran sitio para empezar.

  6. Angel Moya Autor del artículo

    Parece que es algún problema con el xml, comprueba que tienes bien todas las etiquetas, donde se abren y cierran, y que la primera linea es o

  7. gabriel

    El mismo error que el compañero anterior:
    File “lxml.etree.pyx”, line 2706, in lxml.etree.parse (src/lxml/lxml.etree.c:49958)
    File “parser.pxi”, line 1522, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:72015)
    File “parser.pxi”, line 1552, in lxml.etree._parseFilelikeDocument (src/lxml/lxml.etree.c:72325)
    File “parser.pxi”, line 1435, in lxml.etree._parseDocFromFilelike (src/lxml/lxml.etree.c:71240)
    File “parser.pxi”, line 997, in lxml.etree._BaseParser._parseDocFromFilelike (src/lxml/lxml.etree.c:68381)
    File “parser.pxi”, line 539, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:64257)
    File “parser.pxi”, line 625, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:65178)
    File “parser.pxi”, line 565, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:64521)
    XMLSyntaxError: Start tag expected, ‘<' not found, line 1, column 1

    Lograron ver alguna solución???

    Excelente

  8. gabriel

    Ya me autoconteste, lo que veo es que el archivo xml, esta diferente a como debería de estar para que openerp lo pueda leer, puede ser un copy y page en la página.
    Para que funcione de maravilla tiene que estar de la siguiente forma:

    coche
    coche
    form

    coche
    coche
    tree

    Coche
    coche
    tree,form

  9. Elba Campos

    Gran ayuda! Los que le da error en el xml es porque deben sustituria los &.. por las asi como los espacios.. Felicidades.. Que haríamos los informáticos sin gente que colgara etas ayudas en la web!

  10. Alejandro Torres

    Buenas Tardes, quiero felicitarlos por los aportes que realizan a este blog, y al creador del mismo, estoy intentando montar el modulo de coche pero me arroja el siguiente error:

    zimp.load_module(m)
    ZipImportError: bad local file header in /home/alejandrot/openERP/openerp-server-5.0.7/bin/addons/coche.zip

    Espero me puedan colaborar.

  11. Angel Moya Autor del artículo

    Iba a decirte que probases a copiar el módulo en lugar de importarlo… pero veo que ya lo has solucionado.

  12. Angel Moya Autor del artículo

    Buenas, lo siento pero el ejemplo lo hice hace mucho tiempo y no dejé enlazado el código en ningún sitio, tocaría copiar y pegar.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *