Construcción de modulo en Odoo 10
Construcción de modulo en Odoo 10
Iniciar/detener el servidor Odoo
Iniciar/detener el servidor Odoo
Odoo utiliza una arquitectura cliente / servidor en el que los clientes son los navegadores web que acceden al Odoo utiliza una arquitectura cliente / servidor en el que los clientes son los navegadores web que acceden al servidor Odoo a través de RPC.
servidor Odoo a través de RPC.
La lógica de negocio y la extensión se lleva a cabo generalmente en el lado del servidor, aunque apoyan las La lógica de negocio y la extensión se lleva a cabo generalmente en el lado del servidor, aunque apoyan las funciones del cliente (por ejemplo, una nueva representación de datos tales como mapas interactivos) puede ser funciones del cliente (por ejemplo, una nueva representación de datos tales como mapas interactivos) puede ser añadido al cliente.
añadido al cliente.
Con el fin de iniciar el servidor, basta con invocar el comando
Con el fin de iniciar el servidor, basta con invocar el comando odoo-bin odoo-bin en la cáscara, la adición de la ruta completa alen la cáscara, la adición de la ruta completa al archivo si es necesario:
archivo si es necesario:
odoo
odoo-- binbin
El servidor es detenido por golpear
El servidor es detenido por golpear Ctrl-CCtrl-Cdos veces desde el terminal, o matando el proceso OS correspondiente.dos veces desde el terminal, o matando el proceso OS correspondiente.
Construir un módulo Odoo
Construir un módulo Odoo
AmbasAmbas extensiones extensiones de de servidor servidor y cy cliente liente se se empaquetan empaquetan comocomo módulosmódulos que se cargan opcionalmente en una que se cargan opcionalmente en una basebase de datos
de datos..
Los módulos Odoo puede agregar nueva lógica de negocio a un sistema, o modificar y ampliar la lógica de negocio Los módulos Odoo puede agregar nueva lógica de negocio a un sistema, o modificar y ampliar la lógica de negocio existente: un módulo puede ser creado para añadir reglas de contabilidad de su país para el apoyo de la contabilidad existente: un módulo puede ser creado para añadir reglas de contabilidad de su país para el apoyo de la contabilidad general de Odoo, mientras que el siguiente módulo añade soporte para la visualización en tiempo real de una flota de general de Odoo, mientras que el siguiente módulo añade soporte para la visualización en tiempo real de una flota de autobuses. Todo en Odoo por lo tanto comienza y termina con módulos.
autobuses. Todo en Odoo por lo tanto comienza y termina con módulos.
Composición de un módulo
Composición de un módulo
Un móduloUn módulo Odoo Odoo puede contener una puede contener una serie de elementos:serie de elementos:
Objetos de negocio (
Objetos de negocio (Business objectsBusiness objects))
Declarado como clases de Python, estos recursos se conservan automáticamente por Odoo basado en su Declarado como clases de Python, estos recursos se conservan automáticamente por Odoo basado en su configuración
configuración
Archivos de información (
Archivos de información (Data filesData files))
XML o CSV archivos de metadatos que declaran (vistas o flujos de trabajo), los datos de configuración (módulos XML o CSV archivos de metadatos que declaran (vistas o flujos de trabajo), los datos de configuración (módulos de parametrización), datos de demostración y más
de parametrización), datos de demostración y más
Controladores web (
Controladores web (Web controllersWeb controllers))
Manejar las solicitudes de los navegadores Web Manejar las solicitudes de los navegadores Web
Datos de la web estática (
Datos de la web estática (Static web dataStatic web data))
Imágenes, archivos CSS o Javascript empleado por la interfaz web o sitio web Imágenes, archivos CSS o Javascript empleado por la interfaz web o sitio web
Estructura del módulo
Estructura del módulo
Cada módulo es un directorio dentro de unCada módulo es un directorio dentro de un directorio de módulosdirectorio de módulos. Los directorios módulo se especifican mediante el uso de la. Los directorios módulo se especifican mediante el uso de la -- --addons-path
addons-pathopción.opción.
Tip
Tip
La mayoría de las opciones de línea de comandos también se pueden configurar mediante
La mayoría de las opciones de línea de comandos también se pueden configurar mediante
un a
un a
rchi
rchi
vo
vo
de
de
config
config
uración
uración
..Un módulo Odoo se declara por su
Un módulo Odoo se declara por su manifiesta manifiesta(manifest). Consulte la(manifest). Consulte la documentación de manifiesto documentación de manifiestoal respecto.al respecto. Un módulo es también un
Un módulo es también unpaquete paquete de de PythonPythoncon un archivocon un archivo__init__.py__init__.py, que contiene instrucciones de, que contiene instrucciones de importación para diversos archivos de Python en el módulo.
importación para diversos archivos de Python en el módulo. Por ejemplo, si el módulo tiene un solo
Por ejemplo, si el módulo tiene un solomymodule.pymymodule.py archivoarchivo__init__.py__init__.py puede contener: puede contener: from
from .. importimport mymodulemymodule
Odoo proporciona un mecanismo para ayudar a configurar un nuevo módulo,
Odoo proporciona un mecanismo para ayudar a configurar un nuevo módulo, odoo-bin odoo-bin tiene untiene un subcomando
subcomando scaffoldscaffold para crear un módulo vacío:para crear un módulo vacío:
$
El comando crea un subdirectorio para su módulo, y crea automáticamente un montón de archivos estándar para un El comando crea un subdirectorio para su módulo, y crea automáticamente un montón de archivos estándar para un módulo. La mayoría de ellos simplemente contener código XML o comentado. El uso de la mayor parte de esos módulo. La mayoría de ellos simplemente contener código XML o comentado. El uso de la mayor parte de esos archivos se explicará a lo largo de este tutorial.
archivos se explicará a lo largo de este tutorial.
Ejercicio Ejercicio
Creación de módulos Creación de módulos
Utilice la línea de comandos anterior para crear un módulo vacío abierto Academia, e instalarlo en Odoo. Utilice la línea de comandos anterior para crear un módulo vacío abierto Academia, e instalarlo en Odoo.
1.
1. Invocar Invocar el el comandocomando odoo-bin scaffold openacademy addonsodoo-bin scaffold openacademy addons.. 2.
2. Adaptar Adaptar el el archivo archivo de de manifiesto manifiesto a a su su módulo.módulo. 3.
3. No No preocuparse preocuparse por por los los demás demás archivos.archivos.
Mapeo
Mapeo
objeto-relac
objeto-relac
ional
ional
Un componente clave de Odoo es la capa ORM. Esta capa evita tener que escribir la mayor parte de SQL con la Un componente clave de Odoo es la capa ORM. Esta capa evita tener que escribir la mayor parte de SQL con la mano y proporciona servicios de extensibilidad y seguridad (
mano y proporciona servicios de extensibilidad y seguridad ( 2 2 ).).
Los objetos de negocio se declaran como clases de Python que se extienden
Los objetos de negocio se declaran como clases de Python que se extienden ModelModel,, que los integra en el sistema que los integra en el sistema automatizado de persistencia.
automatizado de persistencia.
Los modelos pueden ser configurados mediante el establecimiento de una serie de atributos bajo su definición. El Los modelos pueden ser configurados mediante el establecimiento de una serie de atributos bajo su definición. El atributo más importante es
atributo más importante es _name _name que se requiere y define el nombre para el modelo en el sistema Odoo. He aquíque se requiere y define el nombre para el modelo en el sistema Odoo. He aquí una definición mínimamente completa de un modelo:
una definición mínimamente completa de un modelo:
from
from odooodoo importimport modelsmodels
class
class MinimalModelMinimalModel(models(models..Model):Model):
_name
_name == 'test.model''test.model'
Campos del modelo
Campos del modelo
Los campos que se utilizan para definir lo que el modelo puede almacenar y dónde. Los campos son definidos como Los campos que se utilizan para definir lo que el modelo puede almacenar y dónde. Los campos son definidos como atributos en la clase del modelo:
atributos en la clase del modelo:
from
from odooodoo importimport models,models, fieldsfields
class
class LessMinimalModelLessMinimalModel(models(models..Model):Model):
_name
_name == 'test.model2''test.model2'
name
name == fieldsfields..Char()Char()
Los atributos comunes
Los atributos comunes
Al igual que el modelo en sí, sus campos se pueden configurar, mediante el paso
Al igual que el modelo en sí, sus campos se pueden configurar, mediante el paso de configuración de atributos comode configuración de atributos como parámetros:
parámetros:
name
name == fieldfield..Char(requiredChar(required==True)True)
Algunos atributos están disponibles en todos los campos, estos son los más comunes: Algunos atributos están disponibles en todos los campos, estos son los más comunes:
string( unicode, Por defecto: el nombre del campo) string( unicode, Por defecto: el nombre del campo)
La etiqueta del campo en la interfaz de usuario (visible por los usuarios). La etiqueta del campo en la interfaz de usuario (visible por los usuarios).
required( bool, Por defecto: False) required( bool, Por defecto: False)
Si el campo
Si el campo TrueTrue no puede estar vacío, o bien debe tener un valor por defecto o que siempre se le da un no puede estar vacío, o bien debe tener un valor por defecto o que siempre se le da un valor al crear un registro.
valor al crear un registro.
help( unicode, Por defecto: '') help( unicode, Por defecto: '')
Formato largo, proporciona una información sobre herramientas ayuda a los usuarios en la interfaz de Formato largo, proporciona una información sobre herramientas ayuda a los usuarios en la interfaz de usuario.
usuario.
index( bool, Por defecto: False) index( bool, Por defecto: False)
Pide que Odoo crear un
Pide que Odoo crear un índice de base de datos índice de base de datos en la columna.en la columna. Por defecto en Odoo se escribe default.
Campos simples
Campos simples
Hay dos amplias categorías de campos: campos "simples", que son valores atómicos almacenados directamente en Hay dos amplias categorías de campos: campos "simples", que son valores atómicos almacenados directamente en la mesa del modelo y campos "relacionales" vinculación de registros (del mismo modelo o de diferentes modelos). la mesa del modelo y campos "relacionales" vinculación de registros (del mismo modelo o de diferentes modelos). Ejemplo de campos simples son
Ejemplo de campos simples son BooleanBoolean,,DateDate,, Char Char ..
Campos reservados
Campos reservados
Odoo crea algunos campos en todos los modelos (
Odoo crea algunos campos en todos los modelos ( 1 1 ). Estos campos son gestionados por el sistema y no se deben). Estos campos son gestionados por el sistema y no se deben escribirse. Pueden ser leídos si útil o necesario:
escribirse. Pueden ser leídos si útil o necesario:
id
id(( IdId))
El identificador único para un registro en su modelo. El identificador único para un registro en su modelo.
create_date
create_date(( DatetimeDatetime))
Fecha de creación del registro. Fecha de creación del registro.
create_uid
create_uid(( Many2oneMany2one))
Usuario que creó el registro. Usuario que creó el registro.
write_date
write_date(( DatetimeDatetime))
Fecha de la última modificación del registro. Fecha de la última modificación del registro.
write_uid
write_uid(( Many2oneMany2one))
Usuario que modificó por última vez el registro. Usuario que modificó por última vez el registro.
Los
Los
cam
cam
pos
pos
especia
especia
le
le
s
s
Por defecto, Odoo también requiere un campo
Por defecto, Odoo también requiere un campo namename en todos los modelos para diferentes comportamientos deen todos los modelos para diferentes comportamientos de visualización y búsqueda. El campo que se utiliza para estos fines puede ser anulado por el ajuste
visualización y búsqueda. El campo que se utiliza para estos fines puede ser anulado por el ajuste _rec_name _rec_name..
Ejercicio
Ejercicio
Definir un modelo
Definir un modelo
Definir un nuevo modelo de datos
Definir un nuevo modelo de datos
curso
curso
en el módulo
en el módulo
openacademy
openacademy
. Un curso tiene un título y una
. Un curso tiene un título y una
descripción. Los cursos deben tener un título.
descripción. Los cursos deben tener un título.
Editar el archivo
Editar el archivo
openacademy/models/models.pyopenacademy/models/models.pypara incluir un
para incluir un
curso
curso
de clases.
de clases.
openacademy/models.py
openacademy/models.py
fromfrom odooodoo importimport models,models, fields,fields, apiapi
class
class CourseCourse(models(models..Model):Model):
_name
_name == 'openacademy.course''openacademy.course'
name
name == fieldsfields..Char(stringChar(string=="Title""Title",, requiredrequired==True)True)
description
description == fieldsfields..Text()Text()
Archivo
Archivo
s de inf
s de inf
ormación
ormación
Odoo es un sistema altamente impulsado por datos. Aunque el comportamiento se personaliza mediante código Odoo es un sistema altamente impulsado por datos. Aunque el comportamiento se personaliza mediante código Python, una parte del valor de un módulo se encuentra en los datos que establece al cargarse.
Python, una parte del valor de un módulo se encuentra en los datos que establece al cargarse.
Tip
Tip Existen algunos módulos únicamente para añadir datos en OdooExisten algunos módulos únicamente para añadir datos en Odoo Los módulos de datos se declara a través de
Los módulos de datos se declara a través de data filesdata files,, archivos XML con elementos archivos XML con elementos <record><record>. Cada. Cada elemento
elemento <record><record>crea o actualiza un registro de base de datos.crea o actualiza un registro de base de datos.
<odoo>
<odoo>
<data>
<data>
<record
<record model=model="{model name}""{model name}" id=id="{record identifier}""{record identifier}">>
<field
<field name=name="{a field name}""{a field name}">>{a value}{a value}</field></field>
</record> </record> </data> </data> </odoo> </odoo>
modelmodel es el nombre del modelo Odoo para el registro. es el nombre del modelo Odoo para el registro.
idides unes un identificador externoidentificador externo, permite referír al registro (sin necesidad de conocer su identificador en la base, permite referír al registro (sin necesidad de conocer su identificador en la base de datos).
de datos).
<field><field> elementos tienen unelementos tienen un namename que es el nombre del campo en el modelo (por ejemploque es el nombre del campo en el modelo (por ejemplo descriptiondescription). Su). Su cuerpo es el valor del campo.
cuerpo es el valor del campo.
Los archivos de información tienen que ser declarados en el archivo de manifiesto para ser cargados, pueden ser Los archivos de información tienen que ser declarados en el archivo de manifiesto para ser cargados, pueden ser declaradas en la lista
declaradas en la lista'data''data' (siempre cargado) o en la lista (siempre cargado) o en la lista 'demo''demo' (sólo se cargan en modo de demostración). (sólo se cargan en modo de demostración).
Ejercicio
Ejercicio
Definir los datos de
Definir los datos de
demostrac
demostrac
ión
ión
Crear datos de demostración llenando el modelo de Cursos con unos cuantos cursos de demostración.
Crear datos de demostración llenando el modelo de Cursos con unos cuantos cursos de demostración. Editar elEditar el archivo
archivoopenacademy/demo/demo.xmlopenacademy/demo/demo.xmlpara incluir algunos datos.para incluir algunos datos.
openacademy/demo.xml
openacademy/demo.xml
<odoo> <odoo> <data> <data> <record<record model=model="openacademy.course""openacademy.course" id=id="course0""course0">> <field
<field name=name="name""name">>Course 0Course 0</field></field> <field
<field name=name="description""description">>Course 0's descriptionCourse 0's description Can have multiple lines
Can have multiple lines </field> </field> </record> </record> <record
<record model=model="openacademy.course""openacademy.course" id=id="course1""course1">> <field
<field name=name="name""name">>Course 1Course 1</field></field> <!-- no description for this one -->
<!-- no description for this one -->
</record> </record> <record
<record model=model="openacademy.course""openacademy.course" id=id="course2""course2">> <field
<field name=name="name""name">>Course 2Course 2</field></field> <field
<field name=name="description""description">>Course 2's Course 2's descriptiodescriptionn</field></field> </record> </record> </data> </data> </odoo> </odoo>
Acciones
Acciones
y Menú
y Menú
s
s
Acciones y menús son registros regulares en la base de datos, normalmente declarados a través de archivos de Acciones y menús son registros regulares en la base de datos, normalmente declarados a través de archivos de
datos. Las acciones pueden ser activadas de tres maneras: datos. Las acciones pueden ser activadas de tres maneras:
1.
1. haciendo haciendo clic en clic en los ellos elementos de ementos de menú (vinculado menú (vinculado a accia acciones específicas)ones específicas) 2.
2. haciendo clic haciendo clic en los en los botones en las botones en las vistas (si vistas (si éstos están éstos están conectados a las conectados a las acciones)acciones) 3.
3. como como acciones acciones contextuales contextuales en en objetosobjetos
Debido a que los menús son algo complejas, para declarar hay un acceso directo
Debido a que los menús son algo complejas, para declarar hay un acceso directo <menuitem><menuitem> para para declarardeclarar una
unair.ui.menuir.ui.menuy conectarlo a la acción correspondiente con mayor facilidad.y conectarlo a la acción correspondiente con mayor facilidad.
<record
<record model=model="ir.actions.act_window""ir.actions.act_window" id=id="action_list_ideas""action_list_ideas">>
<field
<field name=name="name""name">>IdeasIdeas</field></field>
<field
<field name=name="res_model""res_model">>idea.ideaidea.idea</field></field>
<field
<field name=name="view_mode""view_mode">>tree,formtree,form</field></field>
</record>
</record>
<menuitem
<menuitem id=id="menu_ideas""menu_ideas" parent=parent="menu_root""menu_root" name=name="Ideas""Ideas" sequence=sequence="10""10"
action=
action="action_list_ideas""action_list_ideas"/>/>
Peligro
Peligro
La acción debe ser declarado antes de su correspondiente menú en el archivo XML. La acción debe ser declarado antes de su correspondiente menú en el archivo XML. Los archivos de datos se ejecutan secuencialmente, el
Los archivos de datos se ejecutan secuencialmente, el ididde la acción de la acción debe estar presente edebe estar presente en la base de n la base de datosdatos antes de que se puede crear el menú.
antes de que se puede crear el menú.
Ejercicio
Ejercicio
Definir nuevas entradas de menú
Definir nuevas entradas de menú
Definir nuevas entradas de menú para acceder a los cursos bajo la entrada del menú OpenAcademy. Un usuario Definir nuevas entradas de menú para acceder a los cursos bajo la entrada del menú OpenAcademy. Un usuario debe ser capaz de:
debe ser capaz de:
mostrar mostrar una una lista lista de de todos todos los los cursoscursos
crear crear / / modificar modificar cursoscursos
1. Crear
1. Crearopenacademy/views/openacademy.xmlopenacademy/views/openacademy.xmlcon una acción y los menús que desencadenan la accióncon una acción y los menús que desencadenan la acción 2.
2. Añadirlo Añadirlo a a la la listalista datadata de deopenacademy/__manifest__.pyopenacademy/__manifest__.py openacademy/__manifest__.py openacademy/__manifest__.py 'data' 'data':: [[ # 'security/ir.model.access.csv', # 'security/ir.model.access.csv', 'templates.xml' 'templates.xml',, 'views/openacademy.xml' 'views/openacademy.xml',, ], ], # only loaded
# only loaded in demonstration modein demonstration mode
'demo' 'demo':: [[
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?> <odoo> <odoo> <data> <data> <!-- window action --> <!-- window action --><!--La siguiente etiqueta es una definición de
La siguiente etiqueta es una definición de acción para una "acción de acción para una "acción de ventana",ventana",
Que
Que es es una una acción acción que que abre abre una una vista vista o o un un conjunto conjunto de de vistas vistas -->-->
<record
<record model=model="ir.actions.act_window""ir.actions.act_window" id=id="course_list_action""course_list_action">> <field
<field name=name="name""name">>CoursesCourses</field></field> <field
<field name=name="res_model""res_model">>openacademy.courseopenacademy.course</field></field> <field
<field name=name="view_type""view_type">>formform</field></field> <field
<field name=name="view_mode""view_mode">>tree,formtree,form</field></field> <field
<field name=name="help""help" type=type="html""html">> <p
<p class=class="oe_view_nocontent_create""oe_view_nocontent_create">>Create the first courseCreate the first course </p> </p> </field> </field> </record> </record>
<!--Menú de nivel superior: sin padre -->
Menú de nivel superior: sin padre -->
<menuitem
<menuitem id=id="main_openacademy_menu""main_openacademy_menu" name=name="Open Academy""Open Academy"/>/> <!-- Se necesita un primer nivel en el menú del lado
<!-- Se necesita un primer nivel en el menú del lado izquierdoizquierdo
Antes de usar la acción = atributo -->
Antes de usar la acción = atributo -->
<menuitem
<menuitem id=id="openacademy_menu""openacademy_menu" name=name="Open Academy""Open Academy"
parent=
parent="main_openacademy_menu""main_openacademy_menu"/>/>
<!-- El menú siguiente debe aparecer * después de *
<!-- El menú siguiente debe aparecer * después de *
Su padre openacademy_me
Su padre openacademy_menu y * nu y * después de su *después de su *
Acción course_list_action -->
Acción course_list_action -->
<menuitem
<menuitem id=id="courses_menu""courses_menu" name=name="Courses""Courses" parent=parent="openacademy_menu""openacademy_menu"
action=
action="course_list_action""course_list_action"/>/>
<!--Ubicación completa de la
Ubicación completa de la identificaciidentificación:ón:
Action
Action = = "openacademy."openacademy.course_listcourse_list_action"_action"
No es necesario cuando es el mismo módulo -->
No es necesario cuando es el mismo módulo -->
</data> </data> </odoo> </odoo>
Basic views
Basic views
Las vistas definen la forma en que se muestran los registros de un modelo. Cada tipo de vista representa un modo de Las vistas definen la forma en que se muestran los registros de un modelo. Cada tipo de vista representa un modo de visualización (una lista de registros, un gráfico de su agregación, ...). Las vistas pueden ser solicitados ya sea de visualización (una lista de registros, un gráfico de su agregación, ...). Las vistas pueden ser solicitados ya sea de forma genérica a través de su tipo (por ejemplo,
forma genérica a través de su tipo (por ejemplo, una lista de sociosuna lista de socios ) o específicamente a través de su ID. Para ) o específicamente a través de su ID. Para solicitudes genéricas, se utilizará la vista con el tipo correcto y la prioridad más baja (lo que la vista de menor solicitudes genéricas, se utilizará la vista con el tipo correcto y la prioridad más baja (lo que la vista de menor prioridad de cada tipo es la vista por defecto para ese tipo).
prioridad de cada tipo es la vista por defecto para ese tipo). View inheritance
Generic view declaration
Generic view declaration
Una vista es declarado como un registro del modelo
Una vista es declarado como un registro del modelo ir.ui.viewir.ui.view. El tipo de vista está implícito en el elemento raíz. El tipo de vista está implícito en el elemento raíz del campo
del campoarcharch::
<record
<record model=model="ir.ui.view""ir.ui.view" id=id="view_id""view_id">>
<field
<field name=name="name""name">>view.nameview.name</field></field>
<field
<field name=name="model""model">>object_nameobject_name</field></field>
<field
<field name=name="priority""priority" eval=eval="16""16"/>/>
<field
<field name=name="arch""arch" type=type="xml""xml">>
<!-- view content: <form>, <tree>, <graph>, ...
<!-- view content: <form>, <tree>, <graph>, ... -->-->
</field> </field> </record> </record>
Peligro
Peligro
El contenido de la vista es XML. El campo
El contenido de la vista es XML. El campo archarch por lo tanto debe ser declarado como por lo tanto debe ser declarado como type="xml"type="xml"para serpara ser analizado correctamente.
analizado correctamente.
Tree views
Tree views
Vistas de árbol, también llamadas vistas de listas, registros de visualización en forma de tabla. Vistas de árbol, también llamadas vistas de listas, registros de visualización en forma de tabla. Su elemento raíz es
Su elemento raíz es <tree><tree>. La forma más simple de la vista de árbol se limita a enumerar todos los campos a. La forma más simple de la vista de árbol se limita a enumerar todos los campos a mostrar en la tabla (cada campo como una columna):
mostrar en la tabla (cada campo como una columna):
<tree
<tree string=string="Idea list""Idea list">>
<field
<field name=name="name""name"/>/>
<field
<field name=name="inventor_id""inventor_id"/>/>
</tree>
</tree>
Form views
Form views
Los formularios se utilizan para crear y editar registros individuales. Los formularios se utilizan para crear y editar registros individuales. Su elemento raíz es
Su elemento raíz es <form><form>. Se componen de elementos de alto nivel de la estructura (grupos, cuadernos) y. Se componen de elementos de alto nivel de la estructura (grupos, cuadernos) y elementos interactivos (botones y campos):
elementos interactivos (botones y campos):
<form
<form string=string="Idea form""Idea form">>
<group
<group colspan=colspan="4""4">>
<group
<group colspan=colspan="2""2" col=col="2""2">>
<separator
<separator string=string="General stuff""General stuff" colspan=colspan="2""2"/>/>
<field
<field name=name="name""name"/>/>
<field
<field name=name="inventor_id""inventor_id"/>/>
</group>
</group>
<group
<group colspan=colspan="2""2" col=col="2""2">>
<separator
<separator string=string="Dates""Dates" colspan=colspan="2""2"/>/>
<field
<field name=name="active""active"/>/>
<field
<field name=name="invent_date""invent_date" readonly=readonly="1""1"/>/>
</group>
</group>
<notebook
<notebook colspan=colspan="4""4">>
<page
<page string=string="Description""Description">>
<field
<field name=name="description""description" nolabel=nolabel="1""1"/>/>
</page>
</page>
</notebook>
</notebook>
<field
<field name=name="state""state"/>/>
</group> </group> </form> </form>
Exercise
Exercise
Personaliza vista form usando XML Personaliza vista form usando XML
Create your own form view for the Course object. Data displayed should be: the name and the description of the Create your own form view for the Course object. Data displayed should be: the name and the description of the course.
course.
openacademy/views/openacademy.xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?> <odoo> <odoo> <data> <data> <record
<record model=model="ir.ui.view""ir.ui.view" id=id="course_form_view""course_form_view">> <field
<field name=name="name""name">>course.formcourse.form</field></field> <field
<field name=name="model""model">>openacademy.courseopenacademy.course</field></field> <field
<field name=name="arch""arch" type=type="xml""xml">> <form
<form string=string="Course Form""Course Form">> <sheet>
<sheet> <group> <group>
<field
<field name=name="name""name"/>/> <field
<field name=name="description""description"/>/> </group> </group> </sheet> </sheet> </form> </form> </field> </field> </record> </record> <!-- window action --> <!-- window action -->
<!--The following tag is an action definition for a "window action",
The following tag is an action definition for a "window action",
Ejercicio
Ejercicio
NOTEBOOK
NOTEBOOK
En la vista Formulario de curso, coloque el campo de descripción bajo una pestaña, de manera que sea más fácil En la vista Formulario de curso, coloque el campo de descripción bajo una pestaña, de manera que sea más fácil agregar otras pestañas más adelante, con información adicional.
agregar otras pestañas más adelante, con información adicional. Modificar el formulario curso de la siguiente manera:
Modificar el formulario curso de la siguiente manera:
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<sheet> <sheet> <group> <group> <field<field name=name="name""name"/>/> </group>
</group> <notebook> <notebook> <page
<page string=string="Description""Description">> <field
<field name=name="description""description"/>/> </page>
</page> <page
<page string=string="About""About">>
This is an example of notebooks This is an example of notebooks </page> </page> </notebook> </notebook> </sheet> </sheet> </form> </form> </field> </field>
Las vistas formulario también pueden usar plano HTML para los diseños más
Las vistas formulario también pueden usar plano HTML para los diseños más flexibles:
flexibles:
<form
<form string=string="Idea Form""Idea Form">>
<header>
<header>
<button
<button string=string="Confirm""Confirm" type=type="object""object" name=name="action_confirm""action_confirm"
states=
states="draft""draft" class=class="oe_highlight""oe_highlight" />/>
<button
<button string=string="Mark as done""Mark as done" type=type="object""object" name=name="action_done""action_done"
states=
states="confirmed""confirmed" class=class="oe_highlight""oe_highlight"/>/>
<button
<button string=string="Reset to draft""Reset to draft" type=type="object""object" name=name="action_draft""action_draft"
states=
states="confirmed,done""confirmed,done" />/>
<field
<field name=name="state""state" widget=widget="statusbar""statusbar"/>/>
</header>
</header>
<sheet>
<sheet>
<div
<div class=class="oe_title""oe_title">>
<label
<label for=for="name""name" class=class="oe_edit_only""oe_edit_only" string=string="Idea Name""Idea Name" />/>
<h1><field
<h1><field name=name="name""name" /></h1>/></h1>
</div>
</div>
<separator
<separator string=string="General""General" colspan=colspan="2""2" />/>
<group
<group colspan=colspan="2""2" col=col="2""2">>
<field
<field name=name="description""description" placeholder=placeholder="Idea description...""Idea description..." />/>
</group>
</sheet> </sheet> </form> </form>
Search views
Search views
Las Vistas de búsqueda personalizar el campo de búsqueda asociado a la vista de la lista (y otras vistas Las Vistas de búsqueda personalizar el campo de búsqueda asociado a la vista de la lista (y otras vistas agregadas). Su elemento raíz es
agregadas). Su elemento raíz es <search><search> y que están compuesto de campos que definen los campos que sey que están compuesto de campos que definen los campos que se pueden buscar en:
pueden buscar en:
<search>
<search>
<field
<field name=name="name""name"/>/>
<field
<field name=name="inventor_id""inventor_id"/>/>
</search>
</search>
Si no existe Buscar en la vista para el modelo, Odoo genera uno que sólo permite la búsqueda en el campo
Si no existe Buscar en la vista para el modelo, Odoo genera uno que sólo permite la búsqueda en el campo namename..
Ejercicio
Ejercicio
Buscar cursos Buscar cursosPermitir la búsqueda de cursos en función de su título o su descripción. Permitir la búsqueda de cursos en función de su título o su descripción.
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
</field> </field> </record> </record> <record<record model=model="ir.ui.view""ir.ui.view" id=id="course_search_view""course_search_view">> <field
<field name=name="name""name">>course.searchcourse.search</field></field> <field
<field name=name="model""model">>openacademy.courseopenacademy.course</field></field> <field
<field name=name="arch""arch" type=type="xml""xml">> <search>
<search> <field
<field name=name="name""name"/>/> <field
<field name=name="description""description"/>/> </search> </search> </field> </field> </record> </record> <!-- window action --> <!-- window action -->
<!--The following tag is an action definition for a "window action",
The following tag is an action definition for a "window action",
Las relaciones entre los modelos
Las relaciones entre los modelos
Un registro de un modelo puede estar relacionado con un registro de otro modelo. Por ejemplo, un registro de orden Un registro de un modelo puede estar relacionado con un registro de otro modelo. Por ejemplo, un registro de orden de venta se relaciona con un registro de cliente que contiene los datos del cliente; También se relaciona con sus de venta se relaciona con un registro de cliente que contiene los datos del cliente; También se relaciona con sus registros de línea de orden de venta
registros de línea de orden de venta
..
Ejercicio
Ejercicio
Crear un modelo de sesión Crear un modelo de sesión
Para el módulo abierto Academia, consideramos un modelo para
Para el módulo abierto Academia, consideramos un modelo para sesionessesiones: una sesión es una ocurrencia de un: una sesión es una ocurrencia de un curso impartido en un momento dado para un público determinado.
curso impartido en un momento dado para un público determinado. Crear un modelo para
Crear un modelo para las sesioneslas sesiones. Una sesión tiene un nombre, una fecha de inicio, una duración y un número de. Una sesión tiene un nombre, una fecha de inicio, una duración y un número de asientos. Añadir una acción y un elemento de menú para mostrarlos. Hacer que el nuevo modelo visible a través de asientos. Añadir una acción y un elemento de menú para mostrarlos. Hacer que el nuevo modelo visible a través de un elemento de menú.
un elemento de menú. 1.
1. Crear Crear la la claseclase de sesiónde sesión en en openacademy/models/models.pyopenacademy/models/models.py.. 2.
2. Añadir Añadir el el acceso acceso al al objeto de objeto de sesión sesión enen openacademy/view/openacademy.xmlopenacademy/view/openacademy.xml..
openacademy/models.py
openacademy/models.py
namename == fieldsfields..Char(stringChar(string=="Title""Title",, requiredrequired==True)True) description
description == fieldsfields..Text()Text()
class
_name
_name == 'openacademy.session''openacademy.session'
name
name == fieldsfields..Char(requiredChar(required==True)True) start_date
start_date == fieldsfields..Date()Date() duration
duration == fieldsfields..Float(digitsFloat(digits==((66,, 22),), helphelp=="Duration in days""Duration in days")) seats
seats == fieldsfields..Integer(stringInteger(string=="Number of seats""Number of seats"))
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<!-- Full id location:<!-- Full id location:
action="opena
action="openacademy.coucademy.course_list_actiorse_list_action"n"
It is not required when it is
It is not required when it is the same module -->the same module -->
<!-- session form view -->
<!-- session form view -->
<record
<record model=model="ir.ui.view""ir.ui.view" id=id="session_form_view""session_form_view">> <field
<field name=name="name""name">>session.formsession.form</field></field> <field
<field name=name="model""model">>openacademy.sessionopenacademy.session</field></field> <field
<field name=name="arch""arch" type=type="xml""xml">> <form
<form string=string="Session Form""Session Form">> <sheet>
<sheet> <group> <group>
<field
<field name=name="name""name"/>/> <field
<field name=name="start_date""start_date"/>/> <field
<field name=name="duration""duration"/>/> <field
<field name=name="seats""seats"/>/> </group> </group> </sheet> </sheet> </form> </form> </field> </field> </record> </record> <record
<record model=model="ir.actions.act_window""ir.actions.act_window" id=id="session_list_action""session_list_action">> <field
<field name=name="name""name">>SessionsSessions</field></field> <field
<field name=name="res_model""res_model">>openacademy.sessionopenacademy.session</field></field> <field
<field name=name="view_type""view_type">>formform</field></field> <field
<field name=name="view_mode""view_mode">>tree,formtree,form</field></field> </record>
</record> <menuitem
<menuitem id=id="session_menu""session_menu" name=name="Sessions""Sessions"
parent=
parent="openacademy_menu""openacademy_menu"
action=
action="session_list_action""session_list_action"/>/> </data> </data> </odoo> </odoo>
Nota
Nota
digits=(6, 2)digits=(6, 2) especifica la precisión de un número float: 6 es el número total de dígitos, mientras que 2 es el númeroespecifica la precisión de un número float: 6 es el número total de dígitos, mientras que 2 es el número de dígitos después de la coma. Tenga en cuenta que da lugar a los números de un teléfono antes de la coma es un de dígitos después de la coma. Tenga en cuenta que da lugar a los números de un teléfono antes de la coma es un máximo de 4.
máximo de 4.
Relational fields
Relational fields
Los campos relacionales enlazan registros, ya sea del mismo modelo (jerarquías) o entre diferentes modelos. Los campos relacionales enlazan registros, ya sea del mismo modelo (jerarquías) o entre diferentes modelos. Los tipos de campos relacionales son:
Los tipos de campos relacionales son:
Many2one(other_mod
Many2one(other_model, ondelete='set null')el, ondelete='set null')
Un simple enlace a otro objeto: Un simple enlace a otro objeto:
print foofoo..other_idother_id..namename
Ver también
Ver también
foreign keys
foreign keys
One2many(ot
One2many(other_model, her_model, related_fieldrelated_field)) Una relación virtual, inversa de una
Una relación virtual, inversa de una Many2oneMany2one.. Un Un One2manyOne2manyse comporta como un contenedor dese comporta como un contenedor de registros, el acceso resulta en un conjunto (posiblemente vacío) de registros:
for
for otherother inin foofoo..other_ids:other_ids:
print otherother..namename
Peligro
Peligro
Debido a que una
Debido a que unaOne2manyOne2manyes una relación virtual, noes una relación virtual, no debedebe haber un campo haber un campoMany2oneMany2oneen elen el
other_model
other_model
, y su, y su nombrenombredebedebe ser ser
related_field
related_field
Many2many(other_model) Many2many(other_model)
Bidireccional relación múltiple, cualquier registro en un lado puede estar relacionado con cualquier número de Bidireccional relación múltiple, cualquier registro en un lado puede estar relacionado con cualquier número de registros en el otro lado. Se comporta como un recipiente de registros, el acceso también resulta en un
registros en el otro lado. Se comporta como un recipiente de registros, el acceso también resulta en un conjunto posiblemente vacío de registros:
conjunto posiblemente vacío de registros:
for
for otherother inin foofoo..other_ids:other_ids:
print otherother..namename
Ejercicio
Ejercicio
las relaciones Many2one las relaciones Many2one
El uso de un many2one, modifique las
El uso de un many2one, modifique las del cursodel curso y la y la SesiónSesión modelos para reflejar su relación con otros modelos: modelos para reflejar su relación con otros modelos:
Un Un curso curso tiene tiene unauna responsabilidad responsabilidad del usuario; el valor de ese campo es un registro del modelo del usuario; el valor de ese campo es un registro del modelo integrado
integrado res.usersres.users..
Una Una sesión sesión tiene tiene unun instructor instructor ; el valor de ese campo es un registro del modelo integrado; el valor de ese campo es un registro del modelo integrado res.partner res.partner ..
Una Una sesión sesión se se relaciona relaciona con con unun supuestosupuesto; el valor de ese campo es un registro del; el valor de ese campo es un registro del modelo
modeloopenacademy.courseopenacademy.coursey no es requerido.y no es requerido.
Adaptar Adaptar los los puntos puntos de de vista.vista. 1.
1. Añadir Añadir los los correspondientes correspondientes camposcampos Many2oneMany2one de los modelos, y de los modelos, y 2.
2. Añadirlos Añadirlos en en las las vistas.vistas.
openacademy/models.py
openacademy/models.py
namename == fieldsfields..Char(stringChar(string=="Title""Title",, requiredrequired==True)True) description
description == fieldsfields..Text()Text() responsible_id
responsible_id == fieldsfields..Many2one(Many2one('res.users''res.users',, ondelete
ondelete=='set null''set null',, stringstring=="Responsible""Responsible",, indexindex==True)True)
class
class SessionSession(models(models..Model):Model): _name
_name == 'openacademy.session''openacademy.session'
start_date
start_date == fieldsfields..Date()Date() duration
duration == fieldsfields..Float(digitsFloat(digits==((66,, 22),), helphelp=="Duration in days""Duration in days")) seats
seats == fieldsfields..Integer(stringInteger(string=="Number of seats""Number of seats")) instructor_id
instructor_id == fieldsfields..Many2one(Many2one('res.partner''res.partner',, stringstring=="Instructor""Instructor")) course_id
course_id == fieldsfields..Many2one(Many2one('openacademy.course''openacademy.course',, ondelete
ondelete=='cascade''cascade',, stringstring=="Course""Course",, requiredrequired==True)True)
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<sheet> <sheet> <group> <group> <field<field name=name="name""name"/>/> <field
<field name=name="responsible_id""responsible_id"/>/> </group>
</group> <notebook> <notebook> <page
<page string=string="Description""Description">> </field>
</field> </record> </record>
<!-- override the automatically generated list view for courses -->
<!-- override the automatically generated list view for courses -->
<record
<record model=model="ir.ui.view""ir.ui.view" id=id="course_tree_view""course_tree_view">> <field
<field
<field name=name="model""model">>openacademy.courseopenacademy.course</field></field> <field
<field name=name="arch""arch" type=type="xml""xml">> <tree
<tree string=string="Course Tree""Course Tree">> <field
<field name=name="name""name"/>/> <field
<field name=name="responsible_id""responsible_id"/>/> </tree> </tree> </field> </field> </record> </record> <!-- window action --> <!-- window action -->
<!--The following tag is an action definition for a "window action",
The following tag is an action definition for a "window action",
<form
<form string=string="Session Form""Session Form">> <sheet>
<sheet> <group> <group>
<group
<group string=string="General""General">> <field
<field name=name="course_id""course_id"/>/> <field
<field name=name="name""name"/>/> <field
<field name=name="instructor_id""instructor_id"/>/> </group>
</group> <group
<group string=string="Schedule""Schedule">> <field
<field name=name="start_date""start_date"/>/> <field
<field name=name="duration""duration"/>/> <field
<field name=name="seats""seats"/>/> </group> </group> </group> </group> </sheet> </sheet> </form> </form> </field> </field> </record> </record>
<!-- session tree/list view -->
<!-- session tree/list view -->
<record
<record model=model="ir.ui.view""ir.ui.view" id=id="session_tree_view""session_tree_view">> <field
<field name=name="name""name">>session.treesession.tree</field></field> <field
<field name=name="model""model">>openacademy.sessionopenacademy.session</field></field> <field
<field name=name="arch""arch" type=type="xml""xml">> <tree
<tree string=string="Session Tree""Session Tree">> <field
<field name=name="name""name"/>/> <field
<field name=name="course_id""course_id"/>/> </tree> </tree> </field> </field> </record> </record> <record
<record model=model="ir.actions.act_window""ir.actions.act_window" id=id="session_list_action""session_list_action">> <field
<field name=name="name""name">>SessionsSessions</field></field> <field
<field name=name="res_model""res_model">>openacademy.sessionopenacademy.session</field></field>
Ejercicio
Ejercicio
Las relaciones inversas One2Many Las relaciones inversas One2Many
Utilizando el inverso one2many campo relacional, modificar los modelos para reflejar la relación entre los cursos y Utilizando el inverso one2many campo relacional, modificar los modelos para reflejar la relación entre los cursos y sesiones.
sesiones. 1.
1. Modificar Modificar la la claseclase CourseCourse y y 2.
2. Agregar el Agregar el campo en campo en la vila vista de sta de formulario de formulario de curso.curso.
openacademy/models.py
openacademy/models.py
responsible_idresponsible_id == fieldsfields..Many2one(Many2one('res.users''res.users',, ondelete
ondelete=='set null''set null',, stringstring=="Responsible""Responsible",, indexindex==True)True) session_ids
session_ids == fieldsfields..One2many(One2many( 'openacademy.session'
'openacademy.session',, 'course_id''course_id',, stringstring=="Sessions""Sessions"))
class
class SessionSession(models(models..Model):Model):
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<page<page string=string="Description""Description">> <field
</page> </page> <page
<page string=string="Sessions""Sessions">> <field
<field name=name="session_ids""session_ids">> <tree
<tree string=string="Registered sessions""Registered sessions">> <field
<field name=name="name""name"/>/> <field
<field name=name="instructor_id""instructor_id"/>/> </tree> </tree> </field> </field> </page> </page> </notebook> </notebook> </sheet> </sheet>
Ejercicio
Ejercicio
Las relaciones múltiples Many2Many Las relaciones múltiples Many2Many
Utilizando el Many2Many campo relacional, modificar la
Utilizando el Many2Many campo relacional, modificar la SesiónSesión modelo para relacionar cada sesión a un conjunto modelo para relacionar cada sesión a un conjunto de
deasistentesasistentes. Los asistentes estarán representados por los registros asociados, por lo que se relacionan con el. Los asistentes estarán representados por los registros asociados, por lo que se relacionan con el modelo integrado
modelo integradores.partner res.partner . Adaptar las vistas en consecuencia.. Adaptar las vistas en consecuencia. 1.
1. Modificar Modificar la la claseclase SessionSession y y 2.
2. agregar agregar el el campo campo en en la la vista vista formulario.formulario.
openacademy/models.py
openacademy/models.py
instructor_idinstructor_id == fieldsfields..Many2one(Many2one('res.partner''res.partner',, stringstring=="Instructor""Instructor")) course_id
course_id == fieldsfields..Many2one(Many2one('openacademy.course''openacademy.course',, ondelete
ondelete=='cascade''cascade',, stringstring=="Course""Course",, requiredrequired==True)True) attendee_ids
attendee_ids == fieldsfields..Many2many(Many2many('res.partner''res.partner',, stringstring=="Attendees""Attendees"))
openacademy/views/openacademy.xml
openacademy/views/openacademy.xml
<field<field name=name="seats""seats"/>/> </group>
</group> </group> </group> <label
<label for=for="attendee_ids""attendee_ids"/>/> <field
<field name=name="attendee_ids""attendee_ids"/>/> </sheet> </sheet> </form> </form> </field> </field>
Herencia
Herencia
Modelo de herencia
Modelo de herencia
Odoo proporciona dos mecanismos
Odoo proporciona dos mecanismos de herenciade herencia para extender un para extender un modelo existente de modelo existente de una forma modular.una forma modular.
El primer mecanismo de herencia permite a un módulo para modificar el comportamiento de un modelo definido en El primer mecanismo de herencia permite a un módulo para modificar el comportamiento de un modelo definido en otro módulo:
otro módulo:
añadir añadir campos campos a a un un modelo,modelo,
anular anular la la definición definición de de campos campos en en un un modelo,modelo,
añadir añadir restricciones restricciones a a un un modelo,modelo,
añadir añadir métodos métodos a a un un modelo,modelo,
reemplazar reemplazar los los métodos métodos existentes existentes en en un un modelo.modelo.
El segundo mecanismo de herencia (delegación) permite vincular cada registro de un modelo para un registro en un El segundo mecanismo de herencia (delegación) permite vincular cada registro de un modelo para un registro en un modelo padre, y proporciona un acceso transparente a los campos del registro padre.
Ver también
Ver también
_inherit _inherit _inherits _inheritsVista herencia
Vista herencia
En lugar de modificar las vistas existentes en su lugar (sobrescribiéndolas), Odoo proporciona una herencia de vistas En lugar de modificar las vistas existentes en su lugar (sobrescribiéndolas), Odoo proporciona una herencia de vistas en la que las vistas de "extensión" de los hijos se aplican encima de las vistas de la raíz y pueden agregar o eliminar en la que las vistas de "extensión" de los hijos se aplican encima de las vistas de la raíz y pueden agregar o eliminar contenido de sus padres.
contenido de sus padres.
Una vista de extensión hace referencia a su matriz usando el campo
Una vista de extensión hace referencia a su matriz usando el campo inherit_idinherit_id, y en lugar de una sola vista su, y en lugar de una sola vista su campo
campoarcharch se compone de cualquier número de elementos se compone de cualquier número de elementos xpathxpath de selección y alterar el co de selección y alterar el co ntenido de su vistantenido de su vista padre:
padre:
<!
<! — —lista de categorias de ideas mejoradas -->lista de categorias de ideas mejoradas -->
<record
<record id=id="idea_category_list2""idea_category_list2" model=model="ir.ui.view""ir.ui.view">>
<field
<field name=name="name""name">>id.category.list2id.category.list2</field></field>
<field
<field name=name="model""model">>idea.categoryidea.category</field></field>
<field
<field name=name="inherit_id""inherit_id" ref=ref="id_category_list""id_category_list"/>/>
<field
<field name=name="arch""arch" type=type="xml""xml">>
<!-- Encontrar la descripción del campo y agregar el campo
<!-- Encontrar la descripción del campo y agregar el campo
Idea_ids después de ella -->
Idea_ids después de ella -->
<xpath
<xpath expr=expr="//field[@name='description']""//field[@name='description']" position=position="after""after">>
<field
<field name=name="idea_ids""idea_ids" string=string="Number of ideas""Number of ideas"/>/>
</xpath> </xpath> </field> </field> </record> </record> expr expr Un
Un XPath XPath expresión seleccionar un solo elemento en la vista padre. Genera un error si coincide con ningúnexpresión seleccionar un solo elemento en la vista padre. Genera un error si coincide con ningún elemento o más de uno
elemento o más de uno
position position
Operación que se aplicará al elemento coincidente: Operación que se aplicará al elemento coincidente:
inside inside
Añade el cuerpo de
replace replace
Sustituye el elemento emparejaron con el cuerpo de
Sustituye el elemento emparejaron con el cuerpo de xpathxpath, en sustitución de cualquier, en sustitución de cualquier $0$0ocurrencia nodo enocurrencia nodo en el nuevo cuerpo con el elemento original,
el nuevo cuerpo con el elemento original,
before before
Inserta el cuerpo
Inserta el cuerpo xpathxpath como un hermano antes del elemento emparejado como un hermano antes del elemento emparejado
after after
Inserta el cuerpo
Inserta el cuerpo xpathxpath como un hermano después del elemento emparejado como un hermano después del elemento emparejado
attributes attributes
Altera los atributos del elemento emparejado usando elementos espec
Altera los atributos del elemento emparejado usando elementos espec ialesialesattributeattribute en el cuerpo de en el cuerpo de xpathxpath Tip
Tip
Cuando búsqueda de un solo elemento, el atributo
Cuando búsqueda de un solo elemento, el atributo positionposition se puede establecer directamente sobre el elemento se puede establecer directamente sobre el elemento que se encuentran. Ambas herencias a continuación le dará el mismo resultado.
que se encuentran. Ambas herencias a continuación le dará el mismo resultado.
<xpath
<xpath expr=expr="//field[@name='description']""//field[@name='description']" position=position="after""after">>
<field
<field name=name="idea_ids""idea_ids" />/>
</xpath>
</xpath>
<field
<field name=name="description""description" position=position="after""after">>
<field
<field name=name="idea_ids""idea_ids" />/>
</field>
</field>
Ejercicio Ejercicio
Alterar el contenido existente Alterar el contenido existente
Utilizando el modelo de herencia, modificar el vigente
Utilizando el modelo de herencia, modificar el vigente sociosocio modelo para añadir un campo booleano modelo para añadir un campo booleano instructor instructor , y un , y un campo Many2Many que corresponde a la relación de sesión - socio
campo Many2Many que corresponde a la relación de sesión - socio
Usar la vista de la herencia, Muestra este campos en la vista formulario de empresa Usar la vista de la herencia, Muestra este campos en la vista formulario de empresa
Nota Nota
Esta es la oportunidad para introducir el modo de desarrollador para inspeccionar la vista, encontrará su ID externo y Esta es la oportunidad para introducir el modo de desarrollador para inspeccionar la vista, encontrará su ID externo y el lugar para poner el nuevo campo.
el lugar para poner el nuevo campo. 1.
1. Crear Crear un un archivoarchivo openacademy/models/partner.pyopenacademy/models/partner.pye importarlo ene importarlo en __init__.py __init__.py
2.
2. Crear Crear un un archivoarchivo openacademy/views/partner.xmlopenacademy/views/partner.xmly añadirlo ay añadirlo a __manifest__.py __manifest__.py
openacademy/__init__.py
openacademy/__init__.py
# coding: utf-8# coding: utf-8
-*-from
from .. importimport controllerscontrollers from
from .. importimport modelsmodels from
from .. importimport partnerpartner
openacademy/__manifest__.py
openacademy/__manifest__.py
# 'security/ir.model.access.csv', # 'security/ir.model.access.csv', 'templates.xml' 'templates.xml',, 'views/openacademy.xml' 'views/openacademy.xml',, 'views/partner.xml' 'views/partner.xml',, ], ], # only loaded# only loaded in demonstration modein demonstration mode
'demo' 'demo':: [[
openacademy/partner.py
openacademy/partner.py
# coding: utf-8 # coding: utf-8 -*-fromfrom odooodoo importimport fields,fields, modelsmodels class
class PartnerPartner(models(models..Model):Model): _inherit
_inherit == 'res.partner''res.partner'
# Agreggue una columna nueva
# Agreggue una columna nueva al modelo res.partner, por defecto los al modelo res.partner, por defecto los partners no sonpartners no son
#
# instructorinstructoreses
instructor
instructor == fieldsfields..Boolean(Boolean("Instructor""Instructor",, defaultdefault==False)False) session_ids
session_ids == fieldsfields..Many2many(Many2many('openacademy.session''openacademy.session',, string
string=="Attended Sessions""Attended Sessions",, readonlyreadonly==True)True)
openacademy/views/partner.xml
openacademy/views/partner.xml
<?xml version="1.0" encoding="UTF-8"?><odoo> <odoo>
<data> <data>
<!-- Add instructor field to existing view
<!-- Add instructor field to existing view -->-->
<record
<record model=model="ir.ui.view""ir.ui.view" id=id="partner_instructor_form_view""partner_instructor_form_view" >> <field
<field name=name="name""name">>partner.instructorpartner.instructor</field></field> <field
<field name=name="model""model">>res.partnerres.partner</field></field> <field
<field name=name="inherit_id""inherit_id" ref=ref="base.view_partner_form""base.view_partner_form"/>/> <field
<field name=name="arch""arch" type=type="xml""xml">> <notebook
<notebook position=position="inside""inside">> <page
<page string=string="Sessions""Sessions">> <group>
<group> <field
<field name=name="instructor""instructor"/>/> <field
<field name=name="session_ids""session_ids"/>/> </group> </group> </page> </page> </notebook> </notebook> </field> </field> </record> </record> <record
<record model=model="ir.actions.act_window""ir.actions.act_window" id=id="contact_list_action""contact_list_action">> <field
<field name=name="name""name">>ContactsContacts</field></field> <field
<field name=name="res_model""res_model">>res.partnerres.partner</field></field> <field
<field name=name="view_mode""view_mode">>tree,formtree,form</field></field> </record>
</record> <menuitem
<menuitem id=id="configuration_menu""configuration_menu" name=name="Configuration""Configuration"
parent=
parent="main_openacademy_menu""main_openacademy_menu"/>/> <menuitem
<menuitem id=id="contact_menu""contact_menu" name=name="Contacts""Contacts"
parent=
parent="configuration_menu""configuration_menu"
action=
action="contact_list_action""contact_list_action"/>/> </data> </data> </odoo> </odoo>
Domains
Domains
En Odoo,
En Odoo,
dominios
dominios
son valores que codifican las condiciones en registros. Un dominio es
son valores que codifican las condiciones en registros. Un dominio es
una lista de
una lista de
los criterios utilizados para seleccionar un subconjunto de los registros de un m
los criterios utilizados para seleccionar un subconjunto de los registros de un m
odelo. Cada criterio es
odelo. Cada criterio es
un triplete, con un nombre de campo,
un triplete, con un nombre de campo,
un operador y un valor.
un operador y un valor.
Por ejemplo, cuando se utiliza en el
Por ejemplo, cuando se utiliza en el
producto
producto
modelo de dominio de la
modelo de dominio de la
siguiente selecciona todos
siguiente selecciona todos
los
los
servicios
servicios
con un precio unitario mayor a
con un precio unitario mayor a
1000
1000
:
:
[([('product_type''product_type',, '=''=',, 'service''service'),), (('unit_price''unit_price',, '>''>',, 10001000)])]
Por criterios predeterminados se combinan con un AND implícito.
Por criterios predeterminados se combinan con un AND implícito.
Los operadores lógicos
Los operadores lógicos
& &(Y),
(Y),
||(OR)
(OR)
y
y
!!(NO) se pueden utilizar para combinar explícitamente crit
(NO) se pueden utilizar para combinar explícitamente crit
erios. Se utilizan en posición prefijo (el
erios. Se utilizan en posición prefijo (el
operador se inserta antes de que sus argumentos en lugar de entre).
operador se inserta antes de que sus argumentos en lugar de entre).
Por ejemplo para seleccionar los
Por ejemplo para seleccionar los
productos "que son servicios de
productos "que son servicios de
O
O
tienen un precio unitario que es
tienen un precio unitario que es
NO
NO
entre 1000 y 2000":
entre 1000 y 2000":
[['|''|',,
(
('product_type''product_type',, '=''=',, 'service''service'),),
'!' '!',, '&''&',, ( ('unit_price''unit_price',, '>=''>=',, 10001000),), ( ('unit_price''unit_price',, '<''<',, 20002000)])]