Some of the information here may be outdated, please check the book instead
[edit]

This page describes how to make Pyjamas work with web2py. It is easy actually and it does not require any additional library other than web2py and pyjamas.

(Updated by Alexei Vinidiktov (alexei.vinidiktov (at) gmail.com) to work with pyjamas 0.5p1 and the built-in jsonrpc gateway of web2py.)

Inspired by this Django page.

Thanks to Luke Kenneth Casson Leighton and Chris Prinos for their help.

web2py is a web framework written in Python. Pyjamas is a Python port of the google web toolkit (written in Java). Pyjamas can be used with web2py to create web applications.

In terms of an MVC framework, web2py acts as the Model and Pyjamas acts as the Views and Controller.

The "Todo List" Application

In this brief tutorial, we will create a very simple todo list. The primary purpose of this tutorial is to briefly demonstrate how to serve data with web2py, how to create and display widgets with Pyjamas, and how to handle user events with Pyjamas.

Prerequesits

Here is the software that is needed:

  • web2py
  • Pyjamas

This tutorial will not go into how to install each of these components, nor their basic usage. Hopefully, some of them can be downloaded as packages for your linux distribution. One reader recommended that you have a fairly recent web2py version.

The Code

Create a new app called "todo"

in models/db.py:

db=SQLDB('sqlite://storage.db')
db.define_table('todo', db.Field('task'))

from gluon.tools import Service     # import rpc services
service = Service(globals())

in controllers/default.py:

def index():
redirect(URL(r=request,f='todoApp'))

@service.jsonrpc
def getTasks():
    todos = db(db.todo.id>0).select()
    return [(todo.task,todo.id) for todo in todos]

@service.jsonrpc
def addTask(taskFromJson):
    db.todo.insert(task= taskFromJson)
    return getTasks()

@service.jsonrpc
def deleteTask (idFromJson):
    del db.todo[idFromJson]
    return getTasks()

def call():
    return service()

def todoApp():
    return dict()

in views/default/todoApp.html

<html>
    <head>
    <meta name="pygwt:module" 
              content="{{=URL(r=request,c='static',f='output/TodoApp')}}">
    <title>Simple Todo Application</title>    
    </head>
    <body bgcolor="white">
        <h1>Simple Todo Application</h1>
        <i>Type a new task to insert in db, click on existing task to delete it</i>
        <script language="javascript" 
                    src="{{=URL(r=request,c='static',f='output/pygwt.js')}}">
        </script>
    </body>
</html>

in static/TodoApp.py: (notice here TodoApp, not todoApp!)

from pyjamas.ui.RootPanel import RootPanel
from pyjamas.ui.Label import Label
from pyjamas.ui.VerticalPanel import VerticalPanel
from pyjamas.ui.TextBox import TextBox
import pyjamas.ui.KeyboardListener
from pyjamas.ui.ListBox import ListBox
from pyjamas.ui.HTML import HTML
from pyjamas.JSONService import JSONProxy

class TodoApp:
    def onModuleLoad(self):
        self.remote = DataService()
        panel = VerticalPanel()

        self.todoTextBox = TextBox()
        self.todoTextBox.addKeyboardListener(self)

        self.todoList = ListBox()
        self.todoList.setVisibleItemCount(7)
        self.todoList.setWidth("200px")
        self.todoList.addClickListener(self)
        self.Status = Label("")

        panel.add(Label("Add New Todo:"))
        panel.add(self.todoTextBox)
        panel.add(Label("Click to Remove:"))
        panel.add(self.todoList)
        panel.add(self.Status)
        self.remote.getTasks(self)        

        RootPanel().add(panel)

    def onKeyUp(self, sender, keyCode, modifiers):
        pass

    def onKeyDown(self, sender, keyCode, modifiers):
        pass


    def onKeyPress(self, sender, keyCode, modifiers):
        """
    This functon handles the onKeyPress event, and will add the item 
    in the text box to the list when the user presses the enter key.  
    In the future, this method will also handle the auto complete feature.
       """
        if keyCode == KeyboardListener.KEY_ENTER and sender == self.todoTextBox:
            id = self.remote.addTask(sender.getText(),self)
            sender.setText("")
            if id<0:
                RootPanel().add(HTML("Server Error or Invalid Response"))

    def onClick(self, sender):
        id = self.remote.deleteTask(sender.getValue(sender.getSelectedIndex()),self)
        if id<0:
            RootPanel().add(HTML("Server Error or Invalid Response"))

    def onRemoteResponse(self, response, request_info):
        self.todoList.clear()
        for task in response:
            self.todoList.addItem(task[0])
            self.todoList.setValue(self.todoList.getItemCount()-1,task[1])

    def onRemoteError(self, code, message, request_info):
        self.Status.setText("Server Error or Invalid Response: ERROR " 
                            + code + " - " + message)

class DataService(JSONProxy):
    def __init__(self):
        JSONProxy.__init__(self, "../../default/call/jsonrpc", 
                            ["getTasks", "addTask","deleteTask"])

if __name__ == '__main__':
    app = TodoApp()
    app.onModuleLoad()

Run Pyjamas before serving the app

cd /path/to/todo/static/
python ~/python/pyjamas-0.5p1/bin/pyjsbuild TodoApp.py
© 2008-2010 by Massimo Di Pierro - All rights reserved - Powered by web2py - design derived from a theme by the earlybird
The content of this book is released under the Artistic License 2.0 - Modified content cannot be reproduced.