Posts by author bertrand.croq

SAVEPOINT transactions

The problem

In a function, you want to perform some operations on a database using sqlalchemy's session. If one of the operations fails, you want the session to go back to its state when the function was called.

The solution

Use a SAVEPOINT transaction:

from nagare import database
def my_func():
    try:
        with database.session.begin(nested=True):
            # let the job be done in a SAVEPOINT transaction
            # if an exception is raised in this block, session's state is restored
            ...
        return True
    except:
        return False

Dynamic content from actions

In the previous post (blog:dynamic_images) we saw how to use the action() method of the img tag to put dynamic images in a view.

Let's see now how to serve any other dynamic content by raising a HTTPOk exception:

import time
from webob.exc import HTTPOk
class MyApp(object):
    def get_text(self, *args):
        data = time.asctime()
        e = HTTPOk()
        e.body = data
        e.content_type = 'text/plain'
        raise e
from nagare import presentation
@presentation.render_for(MyApp)
def render(self, h, *args):
    return h.a('Click me').action(self.get_text)

Nagare catches such webob.exc exceptions; as they inherit from webob.Response they are immediatly returned in the WSGI pipe.

Common HTML structuration for different components

The problem

We want to obtain the same HTML structure when rendering different components.

Templating using inheritance and named views

The principle is the same than the template method design pattern but applied to components views.

Setting the base class

Let's declare an empty base class:

class BaseEntry(object):
    pass

Its default view sets the common HTML structure and embeds the title and properties named views:

from nagare.presentation import render_for
@render_for(BaseEntry)
def render_base_entry(self, h, comp, *args):
    """All the views of entries will have this HTML structure"""
    with h.div(class_='entry'):
        with h.div(class_='title'):
            h << comp.render(h, model='title')
        with h.div(class_='properties'):
            h << comp.render(h, model='properties')
    return h.root

The BaseEntry's title and properties views are empty. They will be redefined for the derived classes:

@render_for(BaseEntry, model='title')
def render_base_entry__header(self, h, *args):
    return h.root
@render_for(BaseEntry, model='properties')
def render_base_entry__properties(self, h, *args):
    return h.root

We can now verify that the basic HTML structure is generated:

>>> from nagare import component
>>> from nagare.namespaces import xhtml
>>>
>>> entry = component.Component(BaseEntry())
>>> h = xhtml.Renderer()
>>> print entry.render(h).write_htmlstring(pretty_print=True)
<div class="entry">
<div class="title"></div>
<div class="properties"></div>
</div>

Using the base class

Now, let's create a derived class:

class SimpleEntry(BaseEntry):
    def __init__(self, name, firstname, age):
        self.name = name
        self.firstname = firstname
        self.age = age

We only have to define its title and properties views:

@render_for(SimpleEntry, model='title')
def render_simple_entry__title(self, h, *args):
    return '%s %s' % (self.firstname, self.name)
@render_for(SimpleEntry, model='properties')
def render_simple_entry__properties(self, h, *args):
    return h.div('Age: %d' % self.age)

for the component data to be correctly inserted into the right HTML structure:

>>> from nagare import component
>>> from nagare.namespaces import xhtml
>>>
>>> entry = component.Component(SimpleEntry('John', 'Doe', 20))
>>> h = xhtml.Renderer()
>>> print entry.render(h).write_htmlstring(pretty_print=True)
<div class="entry">
<div class="title">Doe John</div>
<div class="properties"><div>Age: 20</div></div>
</div>

Templating using aggregation and named views

When inheritance is not wanted, we can define a component whose job is to do the rendering:

class EntryTemplate(object):
    def __init__(self, entry):
        self.entry = entry
@render_for(EntryTemplate)
def render_entry_template(self, h, *args):
    """
    Same code that we used in ``render_BaseEntry``
    but using ``self.entry`` instead of ``self``.
    """
    with h.div(class_='entry'):
        with h.div(class_='title'):
            h << self.entry.render(h, model='title')
        with h.div(class_='properties'):
            h << self.entry.render(h, model='properties')
    return h.root

Let's use it with our SimpleEntry class:

class SimpleEntry(object): # no inheritance anymore
    def __init__(self, name, firstname, age):
        self.name = name
        self.firstname = firstname
        self.age = age

The title and properties views are still the same, but we must now declare a default view to wrap our SimpleEntry component into a EntryTemplate component and render it:

from nagare.component import Component
@render_for(SimpleEntry)
def render_simple_entry(self, h, comp, *args):
    return Component(EntryTemplate(comp)).render(h)

Then we can use the SimpleEntry components exactly like in the previous chapter:

>>> from nagare import component
>>> from nagare.namespaces import xhtml
>>>
>>> entry = component.Component(SimpleEntry('John', 'Doe', 20))
>>> h = xhtml.Renderer()
>>> print entry.render(h).write_htmlstring(pretty_print=True)
<div class="entry">
<div class="title">Doe John</div>
<div class="properties"><div>Age: 20</div></div>
</div>