Posts by author vrialland

Dynamic images in your component views

Dynamic images are often used in web apps, for example to create charts from database data. You create your image in a function and then return the content of the image, with the appropriate response headers.

In many frameworks, you must create a method, bind it to an URL and include this URL in the src property of an img tag. In Nagare you directly associate the method to the img tag.

In this example I've taken the Nagare logo and wrote the current timestamp on it using PIL.

Here's the class definition:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import cStringIO
import time
import pkg_resources
from PIL import Image, ImageDraw
from nagare import presentation
class MyApp(object):
    def get_image(self, h):
        """Returns the modified Nagare logo
        In:
          - ``h`` -- the renderer (not used)
        """
        # Get the Nagare logo
        requirement = pkg_resources.Requirement.parse('nagare')
        img = pkg_resources.resource_stream(requirement, '/static/img/logo.gif')
        # Open the image
        im = Image.open(img)
        draw = ImageDraw.Draw(im)
        # Draw timestamp on it
        draw.text((15, 10), time.asctime(), fill=0xffffff)
        # Save it into a StringIO and return the content
        imgdata = cStringIO.StringIO()
        im.save(imgdata, 'PNG')
        return imgdata.getvalue()

Nothing special here. The interesting part is the rendering method for this component:

1
2
3
 @presentation.render_for(MyApp)
 def render(self, h, *args):
     return h.img.action(self.get_image)

You may have already used the action() method on HTML tags such as a or input. The img tags also have one.

All you have to do is to give to action() a callback, that will take a renderer as argument and will have to return the image data. So I passed to action() the get_image() method of MyApp class. As the function returns the image stream, without explicitly setting the content-type of the HTTP response, Nagare auto discovers the content type and set it by itself.