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.
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
Muchas gracias, lo tendré en cuenta para revisarlo… como se suele decir en estos casos «en mi casa funcionaba» 😉
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.
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.
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.
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
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
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
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!
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.
solucionado problema de permisos
Iba a decirte que probases a copiar el módulo en lugar de importarlo… pero veo que ya lo has solucionado.
donde pudeo descargar el codigo de ese ejemplo
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.