wiki:Version2/Tutoriales/Consola_Web/Tutorial_2_Acciones_en_Panel_Contextual

Version 8 (modified by edulix, 9 years ago) (diff)

--

Introducción

Este es el segundo tutorial de la saga de tutoriales sobre Opengnsys 2 referentes a cómo implementar plugins para la Consola Web. Puedes acceder a la página que lista todos los tutoriales o al tutorial anterior: Tutorial 1: Hello World.

Este segundo tutorial se basa en el anterior, por tanto es preciso haberlo comprendido para poder continuar. En el primer tutorial conseguimos que en el Panel Principal se mostrase la acción "hello", a la que si accedíamos veíamos una página con el estilo de la consola web y en la que el área de contenido mostraba el mensaje "Hello World". Es un tutorial muy sencillo conceptualmente, pero sirve para introducir al desarrollador las nociones básicas de cómo funciona el sistema de plugins de la consola web:

  • La estructura de ficheros y directorios: todo plugin tiene su directorio en plugins/<nombre del plugin>, el código principal del plugin va en __init__.py, la información básica sobre el plugin en plugin.conf y los templates en el subdirectorio templates/.
  • En __init__.py definimos nuestra clase Plugin que hereda de PluginBase y en la que redefinimos las funciones que sean necesarias.
  • El desarrollo se basa en el framework web.py: templates en HTML mezclado con código Python, urls del plugin definidas en un array "self.urls" dentro de la clase Plugin, clases que funcionan como vistas y que llaman a las plantillas con parámetros de entrada, etc.

En este segundo tutorial añadiremos a nuestro plugin una nueva acción que aparecerá en el Panel Contextual del navegador de la consola cuando se esté mostrando un ordenador o una unidad organizativa. En la página asociada a la acción mostraremos un mensaje que diga "Hello Computer <computerName>!" si se trata de un ordenador, o "Hello Organizative Unit <ouName>!" si se trata de una unidad organizativa. Como hemos dicho, nos basaremos en el del plugin del tutorial 1.

Creando la acción

Podríamos reutilizar la acción "hello" que ya tenemos definida, pero ilustrar cómo separar código que realiza acciones diferentes, crearemos una nueva acción, que hemos de declarar en plugin.conf añadiendole el siguiente código:

[action/hello_entity]
description = Displays the text Hello entity! referred to either an Organizative Unit or a Computer
human_name = Say hello to this
appear_in_main_panel = No

Efectivamente, vamos a usar la misma acción para mostrar el mensaje tanto si se trata de una Unidad Organizativa o un Ordenador, dado que la acción es conceptualmente la misma, pero sobre entidades diferentes. Ahora viene el quid de la cuestión, el código de __init__.py:

'''
Hello World! plugin example
'''

from ..pluginbase import PluginBase
import hello

class Plugin(PluginBase):
    '''
    '''
    def enable(self):
        self.actions_for_url = ('navigator/(computer|ou)/(.*)', 'hello_entity')
        self.urls = ('action/hello', hello.HelloView,
            self.get_action_url('hello_entity'), hello.HelloEntityView)

Hemos redefinido (por defecto en PluginBase está definida como un array vacío) la variable self.actions_for_url. Es una lista de pares, parecida a self.urls. En esta lista definimos en qué urls vamos a insertar qué acción. Sólo definimos un par, que dice que en las urls que comiencen con 'navigator/computer/' o 'navigator/ou/' vamos a meter la acción 'hello_entity', mediante expresiones regulares.

Cuando aparece una acción en el panel contextual, necesitamos que aparezca con cierta información. Por ejemplo, tendrá un título, que será el human_name definido para esa acción en plugin.conf anteriormente. También necesita una url, que es la url que llevará acabo dicha acción. Y ¿donde definimos las urls de nuestro plugin? en self.urls. Precisamente eso es lo que hemos hecho. Hemos dicho que cuando se acceda dentro de nuestro plugin (es decir con el prefijo 'plugin/hello_world/') a la url de nuestra acción (self.get_action_url('hello_entity')) se maneje dicha url por la vista HelloEntityView que está en el fichero hello.py (hello.HelloEntityView).

Ahora parémonos un momento más. Cuando se ejecuta una acción del Panel Contextual, queremos que dicha acción se ejecute sobre los elementos mostrados en esa página en la que estamos mostrando el panel. Queremos que la acción sea contextual. En el caso de nuestro tutorial, queremos que la vista HelloEntityView muestre un mensaje personalizado: si la acción se muestra para el ordenador fresa, el mensaje será "Hello Computer fresa!". En el sistema de plugins de opengnsys hemos resuelto cómo pasar esa información a la vista asociada a una acción mediante un "trasvase" de información de la url donde se muestra la acción a la vista que maneja la acción.

¿Cómo conseguimos esto? Fácil: cada elemento entre paréntesis en la url definida para una acción en self.actions_for_url se le pasará como argumento a la vista asociada a dicha acción en self.urls. Los pasos claves son los siguientes:

  1. La url en la que se muestra una acción por ejemplo es 'navigator/computer/fresa'.
  2. La expresión regular que hemos puesto en self.actions_for_url que coincide con esa url es 'navigator/(computer|ou)/(.*)'.
  3. Por tanto la lista de elementos de los paréntesis de la expresión regular es ['computer', 'fresa']
  4. En self.urls hemos definido que la vista asociada a la acción 'hello_view' es hello.HelloEntityView.
  5. En hello.HelloEntityView.GET recibiremos los argumentos 'computer' y 'fresa' del paso 3.

Ahora añadiremos la clase HelloEntityView al fichero hello.py, resultando en:

'''
Hello actions
'''
from __future__ import unicode_literals
from decorators import pi18n
import web

class HelloView:
    @pi18n
    def GET(self):
        return web.ctx.render.plugins.hello_world.helloview(_('Hello World!'))

class HelloEntityView:
    @pi18n
    def GET(self, entity_type, entity_name):
        if entity_type == "computer":
            message = _("Hello Computer %s!") % entity_name
        elif entity_type == "ou":
            message = _("Hello Organizative Unit %s!") % entity_name
        return web.ctx.render.plugins.hello_world.helloview(message)

Como véis hemos hecho unos pequeños cambios. Primero, hemos importado unicode_literals del "futuro" (Python 3). Esto nos garantiza que no tendremos problemas con la codificación de las cadenas, haciendo que por defecto todas sean en UTF-8. También hemos modificado cómo llamamos el template: en vez de crear uno nuevo para nuestra vista, le pasamos al template la cadena que queremos mostrar y así podemos reutilizarlo. También, debido a que el plugin está internacionalizado, usamos el decorador pi18n que nos añade automáticamente la función _ dentro de la función decorada (para saber más sobre la internacionalización de los plugins lee el Tutorial 3: Internacionalización de plugins).

Por último, como dijimos antes, la función GET de nuestra vista ahora toma como parámetros aquellos elementos entre paréntesis de la url de self.actions_for_url como hemos visto antes.

El template de templates/helloview.html ha sido debidamente modificado, quedando así:

$def with (message)
$var title: message
$var tab: panel
$var hierarchy = []

$message

Usando el plugin

Si ya teníamos activado el plugin y ejecutándose el servidor, tendremos o bien reiniciar el servidor o bien desactivar y volver a activar el plugin. Esto es necesario para forzar la recarga del mismo. Luego de hacerlo, podremos ver que siempre que naveguemos por una unidad organizativa o un ordenador, aparecerá la acción que hemos dispuesto (mostrando el texto "Say hello to this"), y al hacer clic saludará correctamente a la entidad correspondiente, sea un ordenador o una unidad organizativa.