Search Posts

web2py SPA tutorial: Creating a single-page application with web2py using LOAD

Using LOAD to insert HTML dynamically into an existing page

One way to speed up web applications is to load only part of a web page at a time using jQuery. You insert HTML into a running page using web2py’s versatile LOAD helper.

This example creates a simple todo list application. What makes it different from a stock web2py app is that while the index() view displays a grid of all the existing tasks, it doesn’t do so directly. Instead, it passes them to a “partial” view file called show tasks.html.

In summary, you:

  • Split the controller into at least two methods. In this case, index() is supplemented by showtasks(), even though the showtasks() isn’t called directly.
  • Split the view up into at least two files. In this case index.html is separated from showtasks.html
  • Uses the LOAD helper in the calling view (index.html in this case, but it could be any view) to insert a view file ( showtasks.html)

Here’s what it will look like when finished:

web2py-spa-index-populated

Here are the step by step instructions to make a single view, single-page app that lets you create, edit, delete, and search tasks using web2py’s powerful SQLFORM.grid view.

Create a new web2py application

From the web2py admin interface, create an application. The name can be anything you want. In this web2py tutorial we’ll name it spa, for Single Page Application.

Create the model

Append this code to the bottom of db.py (a full explanation of web2py’s DAL for a similar model can be found here):

file: /models/db.py

db.define_table('task',
    Field('title',unique=True,notnull=True),
    Field('description','text'),
    Field('priority','integer',default=3,
        requires=IS_IN_SET([1,2,3,4,5],
        labels=[T('Very low'),
                T('Low'),
                T('Medium'),
                T('High'),
                T('Very High')],
        zero=None)),
    Field('completed','boolean',default=False))

Create the controllers

Recall that index.html shrinks and calls showtasks.html. So showtasks.html will need its own controller.

Replace the default index() controller method in default.py

Replace the provided index() controller method in default.py as follows:

# Use layout.html to create the "master" page.
# View will call view file showtasks.html.
def index():
    return locals()

Create a showtasks() controller method in default.py

Still in default.py, add the companion showtasks() method as follows:

# index.html view uses this
def showtasks():
    # Create a grid control.
    # Supports adding, deleting,
    # editing, and searching records.
    return dict(
        grid=SQLFORM.grid(
            db.task,user_signature=False))

Create the views

You’ll need to replace the provided index.html view and create a showtasks.html view as well.

Replace the default view index.html

Normally your index.html would look something like this:

{{extend 'layout.html'}}
{{if 'message' in globals():}}
<h3>{{=message}}</h3>
{{pass}}
{{=grid}}

Instead, we’ll break it up into two parts. Replace the contents of index.html with the following:

file: /views/default/index.html

{{extend 'layout.html'}}
{{=LOAD('default', 'showtasks',ajax=True)}}

Create the showtasks.html view

Create the new view showtasks.html. This is the view called from index.html. Replace the contents of the file generated by web2py with this:

file: /views/default/showtasks.html

{{if 'message' in globals():}}
<h3>{{=message}}</h3>
{{pass}}
{{=grid}}

Let’s see what we have. Navigate to http://127.0.0.1:8000/spa/default/index and you’ll see an empty database:

web2py-spa-index-html

Click the +Add Record button and create a sample record. It behaves as expected:
web2py-spa-create-record

Browse to the showtasks view file directly

To prove to yourself that index.html uses showtasks.html, browse directly to http://127.0.0.1:8000/spa/default/showtasks:

web2py-showtasks-loadYou can see that the grid isn’t styled. That’s because the style sheets are provided by layout.html, which is in turn included by index.html. The showtasks.html view itself has no access to layout.html, as you can see from the code listing above.