web interface

Jean-Paul Calderone exarkun at divmod.com
Wed Nov 9 20:50:03 CET 2005


On Wed, 9 Nov 2005 19:08:28 +0000, Tom Anderson <twic at urchin.earth.li> wrote:
>On Mon, 7 Nov 2005, Ajar wrote:
>
>> I have a stand alone application which does some scientific
>> computations. I want to provide a web interface for this app. The app is
>> computationally intensive and may take long time for running. Can
>> someone suggest me a starting point for me? (like pointers to the issues
>> involved in this,
>
>You're probably best off starting a new process or thread for the
>long-running task, and having the web interface return to the user right
>after starting it; you can then provide a second page on the web interface
>where the user can poll for completion of the task, and get the results if
>it's finished. You can simulate the feel of a desktop application to some
>extent by having the output of the starter page redirect the user to the
>poller page, and having the poller page refresh itself periodically.
>
>What you really want is a 'push' mechanism, by which the web app can
>notify the browser when the task is done, but, despite what everyone was
>saying back in '97, we don't really have anything like that.

Yea, there's no way something like this will work:

# push.tac
from zope.interface import Interface, implements 

from twisted.internet import defer, reactor
from twisted.application import service, internet

from nevow import appserver, loaders, tags, rend, athena

class ICalculator(Interface):
    def add(x, y):
        """
        Add x and y.  Return a Deferred that fires with the result.
        """

class Adder(object):
    implements(ICalculator)

    def add(self, x, y):
        # Go off and talk to a database or something, I don't know.  We'll
        # pretend something interesting is happening here, but actually all
        # we do is wait a while and then return x + y.
        d = defer.Deferred()
        reactor.callLater(5, d.callback, x + y)
        return d


class LongTaskPage(athena.LivePage):   
    docFactory = loaders.stan(tags.html[
        tags.head[
            tags.directive('liveglue'),
            tags.title['Mystical Adding Machine of the Future'],
            tags.script(type="text/javascript")["""

                /* onSubmit handler for the form on the page: ask the server
                 * to add two numbers together.  When the server sends the
                 * result, stick it into the page.
                 */
                function onAdd(x, y) {
                    var d = server.callRemote('add', x, y);   
                    var resultNode = document.getElementById('result-node');
                    d.addCallback(function(result) {
                        resultNode.innerHTML = String(result);
                    });
                    d.addErrback(function(err) {
                        var s = "Uh oh, something went wrong: " + err + ".";
                        resultNode.innerHTML = s
                    });
                    resultNode.innerHTML = "Thinking...";
                    return false;
                }""",
            ],
        ],
        tags.body[
            tags.form(onsubmit="return onAdd(this.x.value, this.y.value);")[
                tags.input(type="text", name="x"),
                "+",
                tags.input(type="text", name="y"),
                "=",
                tags.span(id="result-node")[
                    tags.input(type="submit"),
                ],
            ],
        ],
    ])

class Root(rend.Page):
    docFactory = loaders.stan(tags.html[
        tags.head[
            tags.meta(**{"http-equiv": "refresh", "content": "0;calc"})]])

    def child_calc(self, ctx):
        return LongTaskPage(ICalculator, Adder())

application = service.Application("Push Mechanism, like back in '97")
webserver = internet.TCPServer(8080, appserver.NevowSite(Root()))
webserver.setServiceParent(application)
# eof

Right?  But maybe you can explain why, for those of us who aren't enlightened.

Jean-Paul



More information about the Python-list mailing list