Vistas – Diseñar la Interfaz
Este capítulo le ayudara a construir la interfaz gráfica para sus aplicaciones. Hay varios tipos disponibles de vistas y widgets. Los conceptos de contexto y dominio también juegan un papel fundamental en la mejora de la experiencia del usuario, y aprenderá más sobre esto.
El módulo todo_ui
tiene lista la capa de modelo, y ahora necesita la
capa de vista con la interfaz. Agregara elementos nuevos a la Interfaz de
Usuario y modificara las vistas existentes que fueron agregadas en capítulos
anteriores.
La mejor manera de modificar vistas existentes es usar la herencia, como se explico en el Capítulo 3. Sin embargo, para mejorar la claridad en la explicación, sobre escribirá las vistas existentes, y las reemplazara por unas vistas completamente nuevas. Esto hará que los temas sean más fáciles de entender y seguir.
Es necesario agregar un archivo XML nuevo al módulo, así que comience por
editar el archivo manifiesto __openerp__.py
.
Necesita usar algunos campos del módulo todo_user
, para que sea
configurado como una dependencia:
{ 'name': 'User interface improvements to the To-Do app',
'description': 'User friendly features.',
'author': 'Daniel Reis',
'depends': ['todo_user'],
'data': ['todo_view.xml']
}
Comience con las opciones de menú y las acciones de ventana.
Acciones de ventana
Las acciones de ventana dan instrucciones a la interfaz del lado del cliente. Cuando un usuario hace clic en una opción de menú o en un botón para abrir un formulario, es la acción subyacente la que da instrucciones a la interfaz sobre lo que debe hacer.
Comience por crear la acción de ventana que será usada en las
opciones de menú, para abrir las vistas de las tareas por hacer y de los
estados. Cree el archivo de datos todo_view.xml
con el siguiente
código:
<?xml version="1.0"?>
<openerp>
<data>
<act_window id="action_todo_stage" name="To-Do Task Stages" res_model="todo.task.stage" view_mode="tree,form"/>
<act_window id="todo_app.action_todo_task" name="To-Do Tasks" res_model="todo.task"
view_mode="tree,form,calendar,gantt,graph" target="current"
context="{'default_user_id':uid}" domain="[]" limit="80"/>
<act_window id="action_todo_task_stage" name="To-Do Task Stages"
res_model="todo.task.stage" src_model="todo.task" multi="False"/>
</data>
</openerp>
Las acciones de ventana se almacenan en el modelo ir.actions.act_window
,
y pueden ser definidas en archivos XML usando el acceso directo <act_window>
que recién uso.
La primera acción abre el modelo de estados de la tarea, y solo usa los atributos básicos para una acción de ventana.
La segunda acción usa un ID en el espacio de nombre de todo_app
para
sobre escribir la acción original de tareas por hacer del módulo
todo_app
. Esta usa los atributos de acciones de ventana más
relevantes.
name
: Este es el título mostrado en las vistas abiertas a través de esta acción.res_model
: Es el identificador del modelo de destino.view_mode
: Son los tipos de vista que estarán disponibles. El orden es relevante y el primero de la lista será la vista que se abrirá de forma predeterminada.target
: Si es fijado comonew
, la vista se abrirá en una ventana de dialogo. De forma predeterminada esta fijado acurrent
, por lo que abre la vista en el área principal de contenido.context
: Este fija información de contexto en las vistas de destino, la cual puede ser usada para establecer valores predeterminados en campos o filtros activos, entre otras cosas. Verá más detalles sobre esto en este mismo capítulo.domain
: Es una expresión de dominio que establece un filtro para los registros que estarán disponibles en las vistas abiertas.limit
: Es el número de registros por cada página con vista de lista, 80 es el número predefinido.
La acción de ventana ya incluye los otros tipos de vista las cuales estará examinando en este capítulo: calendar, Gantt y gráfico. Una vez que estos cambios son instalados, los botones correspondientes serán mostrados en la esquina superior derecha, junto a los botones de lista y formulario. Note que esto no funcionará hasta crear las vistas correspondientes.
La tercera acción de ventana demuestra como agregar una opción bajo el botón "Más", en la parte superior de la vista. Estos son los atributos usados para realizar esto:
multi
: Si esta fijado aTrue
, estará disponible en la vista de lista. De lo contrario, estará disponible en la vista de formulario.
Contexto y dominio
Se ha referido varias veces al contexto y al dominio. También se ha visto que las acciones de ventana pueden fijar valores en estos, y que los campos relacionales pueden usarlos en sus atributos. Ambos conceptos son útiles para proveer interfaces más sofisticadas. Vea como.
Contexto de sesión
El contexto es un diccionario que contiene datos de sesión usados por las vistas en el lado del cliente y por los procesos del servidor. Puede transportar información desde una vista hasta otra, o hasta la lógica del lado del servidor. Es usado frecuentemente por las acciones de ventana y por los campos relacionales para enviar información a las vistas abiertas a través de ellos.
Odoo estable en el contexto alguna información básica sobre la sesión actual. La información inicial de sesión puede verse así:
{'lang': 'en_US', 'tz': 'Europe/Brussels', 'uid': 1}
Tiene información del ID de usuario actual, y las preferencias de idioma y zona horaria para la sesión de usuario.
Cuando se usa una acción en el cliente, como hacer clic en un botón, se agrega información al contexto sobre los registros seleccionados actualmente:
active_id
es el ID del registro seleccionado en el formulario,active_model
es el modelo de los registros actuales,active_ids
es la lista de los ID seleccionados en la vista de árbol/lista.
El contexto también puede usarse para proveed valores predeterminados en los campos o habilitar filtros en la vista de destino.
Para fijar el valor predeterminado en el campo user_id
, que
corresponda a la sesión actual de usuario, debe usar:
{'default_user_id': uid}
Y si la vista de destino tiene un filtro llamado filter_my_task
,
podrá habilitarlo usando:
{'search_default_filter_my_tasks': True}
Expresiones de dominio
Los dominios se usan para filtrar los datos de registro. Odoo los
analiza detenidamente para formar la expresión SQL WHERE
usada para
consultar a la base de datos.
Cuando se usa en una acción de ventana para abrir una vista, el dominio fija un filtro en los registros que estarán disponibles en esa vista. Por ejemplo, para limitar solo a las Tareas del usuario actual:
domain=[('user_id', '=', uid)]
El valor uid
usado aquí es provisto por el contexto de sesión. Cuando
se usa en un campo relacional, limitara las opciones disponibles de
selección para ese campo. El filtro de dominio puede también usar
valores de otros campos en la vista. Con esto podrá tener diferentes
opciones disponibles dependiendo de lo seleccionado en otros campos. Por
ejemplo, un campo de persona de contacto puede ser establecido para
mostrar solo las personas de la compañía seleccionada previamente en
otro campo.
Un dominio es una lista de condiciones, donde cada condición es una
tupla ('field', 'operator', 'value')
.
El campo a la izquierda es al cual se aplicara el filtro, y puede ser usada la notación de punto en los campos relaciones.
Los operadores que pueden ser usados son:
=
,like
para coincidencias con el valor del patrón donde el símbolo de guión bajo (_
) coincida con cualquier carácter único, y%
coincida con cualquier secuencia de caracteres.like
para hacer coincidir con el patrón SQL%value%
sensible a mayúsculas, eilike
para coincidencias sin sensibilidad de mayúsculas.- Los operadores
not like
ynot ilike
hacen la operación inversa. child_of
encuentra los hijos directos e indirectos, si las relaciones padre/hijo están configuradas en el modelo de destino.in
ynot
verifican la inclusión en una lista. En este caso, el valor de la derecha debe ser una lista Python. Estos son los únicos operadores que pueden ser usados con valores de una lista. Un caso especial es cuando el lado izquierdo es un campo "a-muchos": aquí el operadorin
ejecuta una operacióncontains
.
Están disponibles los operadores de comparación usuales:
<
menor.>
mayor.<=
menor o igual que.>=
mayor o igual que.=
igual.!=
distinto.
El valor dela derecha puede puede ser una constante o una expresión Python a ser evaluada. Lo que puede ser usado en estas expresiones depende del contexto disponible (no debe ser confundido con el contexto de sesión, discutido en la sección anterior). Existen dos posibles contextos de evaluación para los dominios: del lado del cliente y del lado del servidor.
Para los dominios de campo y las acciones de ventana, la evaluación es
realizada desde el lado del cliente. El contexto de evaluación incluye
aquí los campos disponibles para la vista actual, y la notación de
puntos no esta disponible. Puede ser usados los valores del contexto de
sesión, como uid
y active_id
. Están disponibles los módulo de
Python datetime
y time
para ser usado en las operaciones de fecha y
hora, y también esta disponible la función context_today()
que
devuelve la fecha actual del cliente.
Los dominios usados en las reglas de registro de seguridad y en el
código Python del servidor son evaluados del lado el servidor. El
contexto de evaluación tiene los campos los registros actuales
disponibles, y se permite la notación de puntos. También están
disponibles los registros de la sesión de usuario actual. Al usar
user.id
es equivalente a usar uid
en el contexto de evaluación del
lado del cliente.
Las condiciones de dominio pueden ser combinadas usando los operadores lógicos:
&
para el operador lógicoAND
(el predeterminado).|
para el operador lógicoOR
.!
para el operador lógico de negación.
La negación es usada antes de la condición que será negada. Por ejemplo,
para encontrar todas las tareas que no pertenezca al usuario actual:
['!', ('user_id','=', uid)]
.
Los operadores lógicos AND
y OR
operan en las dos condiciones
siguientes. Por ejemplo:
Para filtrar las tareas del usuario actual o sin un usuario (responsable) asignado:
['|', ('user_id', '=', uid), ('user_id', '=', False)]
Un ejemplo más complejo, usado en las reglas de registro del lado del servidor:
['|', ('message_follower_ids', 'in', [user.partner_id.id]), '|', ('user_id', '=', user.id), ('user_id', '=', False)]
El dominio filtra:
- Todos los registros donde los seguidores (un campo de muchos a muchos) contienen al usuario actual además del resultado de la siguiente condición.
- La siguiente condición es, nuevamente, la unión de otras dos
condiciones: los registros donde el
user_id
es el usuario de la sesión actual o no esta fijado.
Vistas de Formulario
Como se ha visto en capítulos anteriores, las vistas de formulario cumplir con una diseño simple o un diseño de documento de negocio, similar a un documento en papel.
Ahora verá como diseñar vistas de negocio y usar los elementos y widgets disponibles. Esto es hecho usualmente heredando la vista base. Pero para hacer el código más simple, creará una vista completamente nueva para las tareas por hacer que sobre escribirá la definida anteriormente.
De hecho, el mismo modelo puede tener diferentes vistas del mismo tipo.
Cuando se abre un tipo de vista para un modelo a través de una acción,
se selecciona aquella con la prioridad más baja. O como alternativa, la
acción puede especificar exactamente el identificador de la vista que se
usará. La acción que definió al principio de este capítulo solo hace
eso; el view_id
le dice a la acción que use específicamente el
formulario con el ID view_form_todo_task_ui
. Esta es la vista que
creará a continuación.
Vistas de negocio
En una aplicación de negocios podrá diferenciar los datos auxiliares de los datos principales del negocio. Por ejemplo, en su aplicación los datos principales son las tareas por hacer, y las etiquetas y los estados son tablas auxiliares.
Estos modelos de negocio pueden usar diseños de vista de negocio mejorados para mejorar la experiencia del usuario. Si vuelve a ejecutar la vista del formulario de tarea agregada en el Capítulo 2, notará que ya sigue la estructura de vista de negocio.
La vista de formulario correspondiente debe ser agregada después de las acciones y los elementos del menú, que agrego anteriormente, y su estructura genérica es esta:
<record id="view_form_todo_task_ui" model="ir.ui.view">
<field name="name">view_form_todo_task_ui</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<form>
<header><!-- Buttons and status widget --></header>
<sheet><!-- Form content --></sheet>
<!-- History and communication: -->
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" />
<field name="message_ids" widget="mail_thread" />
</div>
</form>
</field>
</record>
Las vistas de negocio se componen de tres área visuales:
- Un encabezado,
header
. - Un
sheet
para el contenido. - Una sección al final de historia y comunicación, "history and communication".
La sección historia y comunicación, con los widgets de red social en la
parte inferior, es agregada por la herencia de su modelo de
mail.thread
(del módulo mail
), y agrega los elementos del ejemplo
XML mencionado anteriormente al final de la vista de formulario. También
vio esto en el Capítulo 3.
La barra de estado del encabezado
La barra de estado en la parte superior usualmente presenta el flujo de negocio y los botones de acción.
Los botones de acción son botones regulares de formulario, y lo más
común es que el siguiente paso sea resaltarlos, usando
class="oe_highlight"
. En el archivo todo_ui/todo_view.xml
podrá
ampliar el encabezado vacío para agregar le una barra de estado:
<header>
<field name="stage_state" invisible="True" />
<button name="do_toggle_done" type="object"
attrs="{'invisible' [('stage_state','in',['done','cancel'])]}"
string="Toggle Done" class="oe_highlight" />
<!-- Add stage statusbar: … -->
</header>
Los botones de acción disponible puede diferir dependiendo en que parte del proceso se encuentre el documento actual. Por ejemplo, un botón Marcar como Hecho no tiene sentido si ya está en el estado "Hecho".
Esto se realiza usando el atributo states
, que lista los estados donde
el botón debería estas visible, como esto: states="draft,open"
.
Para mayor flexibilidad podrá usar el atributo attrs
, el cual forma
condiciones donde el botón debería ser invisible:
attrs="{'invisible' [('stage_state','in', ['done','cancel'])]
.
Estas características de visibilidad también están disponibles para otros elementos de la vista, y no solo para los botones. Verá esto en detalle más adelante en este capítulo.
El flujo de negocio
El flujo de negocio es un widget de barra de estado que se encuentra en un campo el cual representa el punto en el flujo donde se encuentra el registro. Usualmente es un campo de selección "State", o un campo "Stage" muchos a uno. En ambos casos puede encontrarse en muchos módulos de Odoo.
El "Stage" es un campo muchos a uno que se usa en un modelo donde los
pasos del proceso están definidos. Debido a esto pueden ser fácilmente
configurados por el usuario final para adecuarlo a sus procesos específicos
de negocio, y son perfectos para el uso de pizarras kanban
.
El "State" es una lista de selección que muestra los pasos estables y
principales de un proceso, como Nuevo, En Progreso, o Hecho. No pueden
ser configurados por el usuario final, pero son fáciles de usar en la lógica
de negocio. Los "States" también tienen soporte especial para las vistas:
el atributo state
permite que un elemento este habilitado para ser
seleccionado por el usuario dependiendo en el estado en que se encuentre
el registro.
Truco
Es posible obtener un beneficio de ambos mundos, a través del
uso de stages
que son mapeados dentro de los "states". Esto fue
lo que hizo en el capítulo anterior, haciendo disponible a "State"
en los documentos de tareas por hacer a través de un campo calculado.
Para agregar un flujo de "stage" en su encabezado de formulario:
<!-- Add stage statusbar: ... -->
<field name="stage_id" widget="statusbar" clickable="True"
options="{'fold_field': 'fold'}" />
El atributo clickable
permite hacer clic en el widget, para cambiar
la etapa o el estado del documento. Es posible que no querrá esto si el
progreso del proceso debe realizarse a través de botones de acción.
En el atributo options
podrá usar algunas configuraciones
específicas:
fold_fields
, cuando de usa el atributostages
, es el nombre del campo que usa el atributostage
del modelo usa para indicar en cuales etapas debe ser mostrado en negritas o "fold".statusbar_visible
, cuando se usa el atributostates
, lista los estados que deben estar siempre visibles, para mantener ocultos los estados de excepción que se usan para casos menos comunes. Por ejemplo:statusbar_visible="draft,open.done"
.
La hoja canvas
es el área del formulario que contiene los elementos
principales del formulario. Esta diseñada para parecer un documento de
papel, y sus registros de datos, a veces, puede ser referidos como
documentos.
La estructura general del documento tiene estos componentes:
- Información de título y subtítulo.
- Un área de botón inteligente, es la parte superior derecha de los campos del encabezado del documento.
- Un cuaderno con páginas en etiquetas, con líneas de documento y otros detalles.
Título y subtítulo
Cuando se usa el diseño de hoja, los campos que están fuera del bloque
<group>
no se mostrarán las etiquetas automáticamente. Es
responsabilidad de la persona que desarrolla controlar si se muestran
las etiquetas y cuando.
También se puede usar las etiquetas HTML para hacer que el título
resplandezca. Para mejores resultados, el título del documento debe
estar dentro de un elemento HTML div
con la clase oe_title
:
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name"/></h1>
<h3>
<span class="oe_read_only">By</span>
<label for="user_id" class="oe_edit_only"/>
<field name="user_id" class="oe_inline" />
</h3>
</div>
Aquí podrá ver el uso de elementos comunes de HTML como div
, span
,
h1
y h3
.
Etiquetas y campos
Las etiquetas de los campos no son mostradas fuera de las secciones
<group>
, pero podrá mostrarlas usando el elemento <label>
:
- El atributo
for
identifica el campo desde el cual tomará el texto de la etiqueta. - El atributo
string
sobre escribe el texto original de la etiqueta del campo. - Con el atributo
class
también podrá usar las clases CSS para controlar la presentación. Algunas clases útiles son: oe_edit_only
para mostrar lo solo cuando el formulario este modo de edición.oe_read_only
para mostrar lo solo cuando el formulario este en modo de lectura.
Un ejemplo interesante es reemplazar el texto con un ícono:
<label for="name" string=" " class="fafa-wrench"/>
Odoo empaqueta los íconos "Font Awesome", que se usan aquí. Los íconos disponibles puede encontrar se en http://fontawesome.org.
Botones inteligentes
El área superior izquierda puede tener una caja invisibles para colocar botones inteligentes. Estos funcionan como los botones regulares pero pueden incluir información estadística. Como ejemplo agregará un botón para mostrar el número total de tareas realizadas por el dueño de la tarea por hacer actual.
Primero necesita agregar el campo calculado correspondiente a
todo_ui/todo_model.py
. Agregue lo siguiente a la clase TodoTask
:
@api.one
def compute_user_todo_count(self):
self.user_todo_count = self.search_count([('user_id', '=', self.user_id.id)])
user_todo_count = fields.Integer('User To-Do Count', compute='compute_user_todo_count')
Ahora agregará la caja del botón con un botón dentro de ella. Agregue
lo siguiente justo después del bloque div
oe_title
:
<div name="buttons" class="oe_right oe_button_box">
<button class="oe_stat_button" type="action" icon="fa-tasks"
name="%(todo_app.action_todo_task)d" string=""
context="{'search_default_user_id': user_id, 'default_user_id': user_id}"
help="Other to-dos for this user">
<field string="To-dos" name="user_todo_count" widget="statinfo"/>
</button>
</div>
El contenedor para los botones es un elemento HTML div
con las clases
oe_button_box
y oe_right
, para que este alineado con la parte
derecha del formulario.
En el ejemplo el botón muestra el número total de las tareas por hacer que posee el documento responsable. Al hacer clic en el, este las inspeccionara, y si se esta creando tareas nuevas el documento responsable original será usado como predeterminado.
Los atributos usados para el botón son:
class="oe_stat_button"
, es para usar un estilo rectángulo en vez de un botón.icon
, es el ícono que será usado, escogido desde el conjunto de íconos de Font Awesome.type
, será usualmente una acción para la acción de ventana, yname
será el ID de la acción que será ejecutada. Puede usarse la formula%(id-acción-externa)d
, para transformar el ID externo en un número de ID real. Se espera que esta acción abra una vista con los registros relacionados.string
, puede ser usado para agregar texto al botón. No se usa aquí porque el campo que lo contiene ya proporciona un texto.context
, fija las condiciones estándar en la vista destino, cuando se haga clic a través del botón, para los filtros de datos y los valores predeterminados para los registros creados.help
, es la herramienta de ayuda que será mostrada.
Por si solo el botón es un contenedor y puede tener sus campos dentro
para mostrar estadísticas. Estos son campos regulares que usan el widget
statinfo
.
El campo debe ser un campo calculado, definido en el módulo subyacente.
También podrá usar texto estático en vez de o junto a los campos de
statinfo
, como: <div>User's To-dos</div>
Organizar el contenido en formulario
El contenido principal del formulario debe ser organizado usando
etiquetas <group>
. Un grupo es una cuadrícula con dos columnas. Un
campo y su etiqueta ocupan dos columnas, por lo tanto al agregar campos
dentro de un grupo, estos serán apilados verticalmente.
Si anido dos elementos <group>
dentro de un grupo superior,
tendrá dos columnas de campos con etiquetas, una al lado de la otra.
<group name="group_top">
<group name="group_left">
<field name="date_deadline" />
<separator string="Reference"/>
<field name="refers_to"/>
</group>
<group name="group_right">
<field name="tag_ids" widget="many2many_tags"/>
</group>
</group>
Los grupos pueden tener un atributo string
, usado para el título de la
sección. Dentro de una sección de grupo, los títulos también pueden
agregarse usando un elemento separator
.
Truco
Intente usar la opción Alternar la Disposición del Esquema del Formulario del menú de Desarrollo: este dibuja líneas alrededor de cada sección del formulario, permitiendo un mejor entendimiento de como esta organizada la vista actual.
Cuaderno con pestañas
Otra forma de organizar el contenido es el cuaderno, el cual contiene múltiples secciones a través de pestañas llamadas páginas. Esto puede usarse para mantener algunos datos fuera de la vista hasta que sean necesarios u organizar un largo número de campos por tema.
No necesitará esto en su formulario de tareas por hacer, pero el siguiente es un ejemplo que podría agregar en el formularios de etapas de la tarea:
<notebook>
<page string="Whiteboard" name="whiteboard">
<field name="docs"/>
</page>
<page name="second_page">
<!-- Second page content -->
</page>
</notebook>
Se considera una buena practica tener nombres en las páginas, esto hace que la ampliación de estas por parte de otros módulo sea más fiable
Elementos de la vista
Ha visto como organizar el contenido dentro de un formulario, usando elementos como encabezado, grupo y cuaderno. Ahora, podrá ahondar en los elementos de campo y botón y que podrá hacer con ellos.
Botones
Los botones soportar los siguientes atributos:
icon
. A diferencia de los botones inteligentes, los íconos disponibles para los botones regulares son aquellos que se encuentran enaddons/web/static/src/img/icons
.string
, es el texto de descripción del botón.type
, puede serworkflow
,object
oaction
, para activar una señal de flujo de trabajo, llamar a un método Python o ejecutar una acción de ventana.name
, es el desencadenante de un flujo de trabajo, un método del modelo, o la ejecución de una acción de ventana, dependiendo deltype
del botón.args
, se usa para pasar parámetros adicionales al método, si eltype
esobject
.context
, fija los valores en el contexto de la sesión, el cual puede tener efecto luego de la ejecución de la acción de ventana, o al llamar a un método de Python. En el último caso, a veces puede ser usado como un alternativa aargs
.confirm
, agrega un mensaje con el mensaje de texto preguntando por una confirmación.special="cancel"
, se usa en los asistentes, para cancelar o cerrar el formulario. No debe ser usado contype
.
Campos
Los campos tiene los siguientes atributos disponibles. La mayoría es tomado de los que fue definido en el modelo, pero pueden ser sobre escritos en la vista. Los atributos generales son:
name
: identifica el nombre técnico del campo.string
: proporciona la descripción de texto de la etiqueta para sobre escribir aquella provista por el modelo.help
: texto de ayuda a ser usado y que reemplaza el proporcionado por el modelo.placeholder
: proporciona un texto de sugerencia que será mostrado dentro del campo.widget
: sobre escribe el widget predeterminado usado por el tipo de campo. Explorará los widgets disponibles más adelante en este mismo capítulo.options
: contiene opciones adicionales para ser usadas por el widget.class
: proporciona las clases CSS usadas por el HTML del campo.invisible="1"
: invisibiliza el campo.nolabel="1"
: no muestra la etiqueta del campo, solo es significativo para los campos que se encuentran dentro de un elemento<group>
.readonly="1"
: no permite que el campo sea editado.required="1"
: hace que el campo sea obligatorio.
Atributos específicos para los tipos de campos:
sum
,avg
: para los campos numéricos, y en las vistas de lista/árbol, estos agregan un resumen al final con el total o el promedio de los valores.password="True"
: para los campos de texto, muestran el campo como una campo de contraseña.filename
: para campos binarios, es el campo para el nombre del archivo.mode="tree"
: para camposOne2many
, es el tipo de vista usado para mostrar los registros. De forma predeterminada es de árbol, pero también puede ser de formularioform
,kanban
o gráfico.
Para los atributos Booleanos en general, podrá usar True
o 1
para
habilitarlo y False
o 0
(cero) para deshabilitarlo. Por ejemplo,
readonly="1"
y realonly="True"
son equivalentes.
Campos relacionales
En los campos relacionales, podrá tener controles adicionales referentes
a los que el usuario puede hacer. De forma predeterminada el usuario pueden
crear nuevos registros desde estos campos (también conocido como creación
rápida) y abrir el formulario relacionado al registro. Esto puede ser
deshabilitado usando el atributo del campo options
:
options={'no_open': True, 'no_create': True}
El contexto y el dominio también son particulares en los campos relacionales. El contexto puede definir valores predeterminados para los registros relacionados, y el dominio puede limitar los registros que pueden ser seleccionados, por ejemplo, basado en otro campo del registro actual. Tanto el contexto como el dominio pueden ser definidos en el modelo, pero solo son usados en la vista.
Widgets de campo
Cada tipo de campo es mostrado en el formulario con el widget predeterminado apropiado. Pero otros widget adicionales están disponible y pueden ser usados:
Widgets para los campos de texto:
email
: convierte al texto del correo electrónico en un elemento "mail-to" ejecutable.url
: convierte al texto en un URL al que se puede hacer clic.html
: espera un contenido en HTML y lo representa; en modo de edición usa un editor WYSIWYG para dar formato al contenido sin saber HTML.
Widgets para campos numéricos:
handle
: específicamente diseñado para campos de secuencia, este muestra una guía para dibujar líneas en una vista de lista y re ordenarlos manualmente.float_time
: da formato a un valor decimal como tiempo en horas y minutos.monetary
: muestra un campo decimal como un monto en monedas. La moneda a usar puede ser tomada desde un campo comooptions="{'currency_field': 'currency_id'}"
.progressbar
: presenta un decimal como una barra de progreso en porcentaje, usualmente se usa en un campo calculado que computa una tasa de culminación.
Algunos widget para los campos relacionales y de selección:
many2many_tags
: muestran un campo muchos a muchos como una lista de etiquetas.selection
: usa el widget del campo Selección para un campo mucho a uno.radio
: permite seleccionar un valor para una opción del campo de selección usando botones de selección simple.kanban_state_selection
: muestra una luz de semáforo para la lista de selección de esta vistakanban
.priority
: representa una selección como una lista de estrellas a las que se puede hacer clic.
Eventos on-change
A veces necesita que el valor de un campo sea calculado automáticamente
cuando cambia otro campo. El mecanismo para esto se llama on-change
.
Desde la versión o, los eventos on-change
están definidos en la capa
del modelo, sin necesidad de ningún marcado especial en las vistas. Es
se hace creando los métodos para realizar el calculo y enlazándolos al
campo(s) que desencadenara la acción, usando el decorador
@api.onchenge('field1','field2')
.
En las versiones anteriores, ente enlace era hecho en la capa de vista,
usando el atributo onchange
para fijar el método de la clase que sería
llamado cuando el campo cambiara. Esto todavía es soportado, pero es
obsoleto. Tenga en cuenta que los métodos on-change
con el estilo
viejo no pueden ser ampliados usando la API nueva. Si necesita hacer
esto, deberá usar la API vieja.
Vistas dinámicas
Los elementos visibles como un formulario también pueden ser cambiados dinámicamente, dependiendo, por ejemplo de los permisos de usuario o la etapa del proceso en la cual esta el documento.
Estos dos atributos le permiten controlar la visibilidad de los elemento en la interfaz:
groups
: hacen al elemento visible solo para los miembros de los grupos de seguridad específicos. Se espera una lista separada por coma de los ID XML del grupo.states
: hace al elemento visible solo cuando el documento esta en el estado especificado. Espera una lista separada por coma de los códigos de "State", y el modelo del documento debe tener un campo "state".
Para mayor flexibilidad, podrá fijar la visibilidad de un elemento
usando expresiones evaluadas del lado del cliente. Esto puede hacerse
usando el atributo attrs
con un diccionario que mapea el atributo
invisible
al resultado de una expresión de dominio.
Por ejemplo, para hacer que el campo refers_to
sea visible en todos
los estados menos draft
:
<field name="refers_to" attrs="{'invisible': [('state','=','draft')]}" />
El atributo invisible
esta disponible para cualquier elemento, no solo
para los campos. Podrá usarlo en las páginas de un cuaderno o en
grupos, por ejemplo.
El atributo attrs
también puede fijar valores para otros dos atributos:
readonly
y required
, pero esto solo tiene sentido para los campos de
datos, convirtiéndolos en campos que no pueden ser editados u
obligatorios. Con esto podrá agregar alguna lógica de negocio haciendo
a un campo obligatorio, dependiendo del valor de otro campo, o desde un
cierto estado más adelante.
Vistas de lista
Comparadas con las vistas de formulario, las vistas de listas son mucho más simples. Una vista de lista puede contener campos y botones, y muchos de los atributos de los formularios también están disponibles.
Aquí se muestra un ejemplo de una vista de lista para su Tareas por Hacer:
<record id="todo_app.view_tree_todo_task" model="ir.ui.view">
<field name="name">To-do Task Tree</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<tree editable="bottom" colors="gray:is_done==True" fonts="italic: state!='open'" delete="false">
<field name="name"/>
<field name="user_id"/>
</tree>
</field>
</record>
Los atributos para el elemento tree
de nivel superior son:
editable
: permite que los registros sean editados directamente en la vista de lista. Los valores posibles sontop
ybottom
, los lugares en donde serán agregados los registros nuevos.colors
: fija dinámicamente el color del texto para los registros, basándose en su contenido. Es una lista separada por punto y coma de valorescolor:condition
.color
es un color válido CSS (vea http://www.w3.org/TR/css3-color/#html4), ycondition
es una expresión Python que evalúa el contexto del registro actual.fonts
: modifica dinámicamente el tipo de letra para los registro basándose en su contexto. Es similar al atributocolors
, pero este fija el estilo de la letra abold
,italic
ounderline
.create
,delete
,edit
: si se fija afalse
(en minúscula), deshabilita la acción correspondiente en la vista de lista.
Vistas de búsqueda
Las opciones de búsqueda disponibles en las vistas son definidas a
través de una vista de lista. Esta define los campos que serán buscados
cuando se escriba en la caja de búsqueda. También provee filtros
predefinidos que pueden ser activados con un clic, y opciones de
agrupación de datos para los registros en las vistas de lista o kanban
.
Aquí se muestra una vista de búsqueda para las tareas por hacer:
<record id="todo_app.view_filter_todo_task" model="ir.ui.view">
<field name="name">To-do Task Filter</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<search>
<field name="name" domain_filter="['|', ('name','ilike',self),('user_id','ilike',self)]"/>
<field name="user_id"/>
<filter name="filter_not_done" string="Not Done" domain="[('is_done','=',False)]"/>
<filter name="filter_done" string="Done" domain="[('is_done','!=',False)]"/>
<separator/>
<filter name="group_user" string="By User" context="{'group_by':'user_id'}"/>
</search>
</field>
</record>
Podrá ver dos campos que serán buscados: name
y user_id
. En
user_id
tendrá una regla de filtro que hace la "búsqueda si" tanto en la
descripción como en el usuario responsable. Luego tendrá dos filtros
predefinidos, filtrando las "tareas no culminadas" y "tareas
culminadas". Estos filtros pueden ser activados de forma independiente,
y serán unidos por un operador OR
si ambos son habilitados. Los
bloques de filters
separados por un elemento <separator/>
serán
unidos por un operador AND
.
El tercer filtro solo fija un contexto o "group-by". Esto le dice a la
vista que agrupe los registros por ese campo, user_id
en este caso.
Los elementos filed
pueden usar los siguientes atributos:
name
: identifica el campo.string
: proporciona el texto de la etiqueta que será usado, en vez del predeterminado.operator
: le permite usar un operador diferente en vez del predeterminado -=
para campos numéricos yilike
para otros tipos de campos.filter_domain
: puede usarse para definir una expresión de dominio específica para usar en la búsqueda, proporcionando mayor flexibilidad que el atributooperator
. El texto que será buscado se referencia en la expresión usandoself
.groups
: permite hacer que la búsqueda en el campo solo este disponible para una lista de grupos de seguridad (identificado por los Ids XML)
Estos son los atributos disponibles para los elementos filter
:
name
: en un identificador, usado para la herencia o para habilitar la a través de la clavesearch_default_
en el contexto de acciones de ventana.string
: proporciona el texto de la etiqueta que se mostrará para el filtro (obligatorio)domain
: proporciona la expresión de dominio del filtro para ser añadida al dominio activo.context
: es un diccionario de contexto para agregarlo al contexto actual. Usualmente este fija una clavegroup_by
con el nombre del filtro que agrupara los registros.groups
: permite hacer que el filtro de búsqueda solo este disponible para una lista de grupos.
Otros tipos de vista
Los tipos de vista que se usan con mayor frecuencia son los formularios
y las listas, discutidos hasta ahora. A parte de estas, existen otros
tipos de vista, y dará un vistazo a cada una de ellas. Las vistas
kanban
no serán discutidas aquí, ya que las verá en el
Capítulo 8.
Recuerde que los tipos de vista disponibles están definidos en el
atributo view_mode
de la acción de ventana correspondiente.
Vistas de Calendario
Como su nombre lo indica, esta presenta los registros en un calendario. Una vista de calendario para las tareas por hacer puede ser de la siguiente manera:
<record id="view_calendar_todo_task" model="ir.ui.view">
<field name="name">view_calendar_todo_task</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<calendar date_start="date_deadline" color="user_id" display="[name], Stage[stage_id]">
<!-- Fields used for the text of display attribute -->
<field name="name" />
<field name="stage_id" />
</calendar>
</field>
</record>
Los atributos de calendar
son los siguientes:
date_start
: El campo para la fecha de inicio (obligatorio).date_end
: El campo para la fecha de culminación (opcional).date_delay
: El campo para la duración en días. Este puede ser usado en vez dedate_end
.color
: El campo para colorear las entradas del calendario. Se le asignará un color a cada valor en el calendario, y todas sus entradas tendrán el mismo color.display
: Este es el texto que se mostrará en las entradas del calendario. Los campos pueden ser insertados usando[<field>]
. Estos campos deben ser declarados dentro del elementocalendar
.
Vistas de Gantt
Esta vista presenta los datos en un gráfico de Gantt, que es útil para la planificación. Las tareas por hacer solo tiene un campo de fecha para la fecha de límite, pero podrá usarla para tener una vista funcional de un gráfico Gantt básico:
<record id="view_gantt_todo_task" model="ir.ui.view">
<field name="name">view_gantt_todo_task</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<gantt date_start="date_deadline" default_group_by="user_id" />
</field>
</record>
Los atributos que puede ser usados para las vistas Gantt son los siguientes.
date_start
: El campo para la fecha de inicio (obligatorio).date_stop
: El campo para la fecha de culminación. Puede ser reemplazado pordate_delay
.date_delay
: El campo con la duración en días. Puede usarse en vez dedate_stop
.progress
: Este campo proporciona el progreso en porcentaje (entre 0 y 100).default_group_by
: Este campo se usa para agrupar las tareas Gantt.
Vistas de Gráfico
Los tipos de vista de gráfico proporcionan un análisis de los datos, en forma de gráfico o una tabla pivote interactiva.
Agregará una tabla pivote a las tareas por hacer. Primero, necesita
agregar un campo. En la clase TodoTask
, del archivo
todo_ui/todo_model.py
, agregue este línea:
effort_estimate = fields.Integer('Effort Estimate')
También debe ser agregado al formulario de tareas por hacer para que podrá fijar datos allí. Ahora, agregue la vista de gráfico con una tabla pivote:
<record id="view_graph_todo_task" model="ir.ui.view">
<field name="name">view_graph_todo_task</field>
<field name="model">todo.task</field>
<field name="arch" type="xml">
<graph type="pivot">
<field name="stage" type="col" />
<field name="user_id" />
<field name="date_deadline" interval="week" />
<field name="effort_estimate" type="measure" />
</graph>
</field>
</record>
El elemento graph
tiene el atributo type
fijado a pivot
. También
puede ser bar
(predeterminado), pie
o line
. En el caso que sea
"bar", gráfico de barras, adicionalmente se puede usar
stacked="True"
para hacer un gráfico de barras apilado.
graph
debería contener campos que pueden tener estos posibles
atributos:
name
: Identifica el campo que será usado en el gráfico, así como en otras vistas.type
: Describe como será usado el campo, como un grupo de filas (predeterminado), "row", como un grupo de columnas, "col", o como una medida, "mesure".interval
: Solo es significativo para los campos de fecha, es un intervalo de tiempo para agrupar datos de fecha porday
,week
,month
,quarter
oyear
.
Resumen
Aprendió más sobre las vistas e Odoo que son usadas para la construcción de la interfaz. Comenzó agregando opciones de menú y acciones de ventana usadas para abrir las vistas. Fueron explicados en detalle los conceptos de contexto y dominio.
También aprendió como diseñar vistas de lista y configurar opciones de búsqueda usando las vistas de búsqueda. Luego, se describieron de modo general los otros tipos de vista disponibles: calendario, Gantt y gráfico. Las vistas Kanban serán estudiadas más adelante, cuando aprenda como usar Qweb.
Ya ha vistos los modelos y las vistas. En el próximo capítulo, aprenderá como implementar la lógica de negocio del lado del servidor.