1. Alberto Valverde González
  2. rum

Wiki

Clone wiki

rum / WebService

Extending Rum Fields via Web Services

During the development of an internal database application it became necessary to obtain pictures stored in the Oberwolfach Photo database http://owpdb.mfo.de .

For this, I have implemented a JSONP-Service in the Photo database, which can be accessed from outside.

How to feed that into RUM. First create a field. Of course it is a read_only field of the Person resource:

Field('owpdb', read_only=True, sortable=False, searchable=False)

I just use the basic Field class, I will provide the widgets, myself, where I want.

For safety, I place a owpdb attribute to Person, which will yield some dummy value, when accessed.

The widget contains a template and a js-File:

class PhotoLookup(Widget):
    template = "genshi:owconf.templates.owpdb"
    javascript = [JSLink(modname = "owconf", filename='public/js/owpdb.js')]
    css = [CSSLink(modname = "owconf", filename='public/css/owpdb.css')]
    def update_params(self, d):
        super(PhotoLookup, self).update_params(d)
        d.person_id = d.value.person_id

The template is quite basic:

<div xmlns="http://www.w3.org/1999/xhtml"
	  xmlns:py="http://genshi.edgewall.org/"
 	  class="${css_class}">
	<span class="owpdb-lookup"
          py:content="person_id" >Searching...</span>
</div>

The trick is done in Javascript.

dojo.require("dojo.io.script")

dojo.addOnLoad(function()
{
    dojo.forEach(dojo.query("span.owpdb-lookup"), function(lookup_widget){
        var db_id=lookup_widget.textContent;
        dojo.io.script.get({
            url: "http://owpdb.mfo.de/photoByPersonInformixId",
            content: {
                "informix_id": db_id
            },
            timeout: 10000,
            error: function(text) {
                console.log("Some Error calling OWPDB");
                return text;
            },
            handleAs:"text",
            callbackParamName:"callback",
            load: function (result) {
                var parent=lookup_widget.parentNode;
                if (result.found){
                    
                    var img_node=document.createElement("img");
                    var anchor_node=document.createElement("a");
                    dojo.attr(anchor_node, 'href',
                    'http://owpdb.mfo.de/person_detail?id='
                        +result.person_id);
                    anchor_node.appendChild(img_node);
                    dojo.attr(img_node, 'src', 'http://owpdb.mfo.de/photoSmall?id='+result.photo_id);
                    if (result.remark) {
                        dojo.attr(img_node, 'title', result.remark);
                    }
                    
                    
                } else {
                    var anchor_node=document.createElement("a");
                    anchor_node.textContent="Couldn't idenfify the person in the Oberwolfach Photo database.";
                    dojo.attr(anchor_node, "href","http://owpdb.mfo.de");
                    
                }
                parent.appendChild(anchor_node);
                dojo._destroyElement(lookup_widget);
            }
        });
    })

});

The JSONP method in photo database returns output like that, when called as that: http://owpdb.mfo.de/photoByPersonInformixId?informix_id=3815&callback=svhj

svhj({"person_id": 7352, "position": "", "photo_id": 7874, "found": true})

Then I register a widget, where I want it to be shown. For the other cases I register None to indicate, that the field shouldn't be handled by the actions. As a read_only field, it is not used by edit/update, so I don't have to care for that.

for action in ['inline_show']:
    WidgetFactory.register(PhotoLookup(), 
        Person,
        attr='owpdb', action=action)
for action in ['inline_preview', 'inline_index']:
    WidgetFactory.register(None, 
        Person,
        attr='owpdb', action=action)

The advantage of this approach using a webservice call, is that there is a minimal interface beetween the databases:

- it is completely highlevel, and independend of the underlying datastructures... - when the photo database is not available or slow, nothing worse will happen than that the picture is not displayed. In particular, the JSONP call is of course not blocking.

The result is seen on this Screenshot (the widget can of course be also plugged into other view, like index table view):

screenshot

Updated