Porting Rails Flickr Example

Note: There is an updated version of this tutorial for Pylons 0.9 here: http://pylonshq.com/project/pylonshq/wiki/RailsFlickrExample0_9

By now you probably have allready seen the  amazing screencast where someone implements a beautiful web interface to Flickr! in under 5 minutes. Well if you haven't seen it yet, you really should do so now. But if you have you would probably be glad to know that this is possible under Pylons too!

On With The Show

Create your project:

paster create --template=pylons imagesearch

In another window, cd into the project directory you just created (you should see development.ini) and start the server:

paster serve --reload development.ini

Back in the first window, chdir into your project directory and create a controller:

cd imagesearch
paster controller flickr

Ok. Now we need an API to Flickr! and an API-KEY. You can  get your API-KEY here. As API, i picked  flickr.py from  this list. Now install your API and make it available to Pylons:

cd imagesearch/lib
curl http://jamesclarke.info/projects/flickr/flickr.py > flickrapi.py

Ok, we're set. Start your stopwatch and let's go!

Autohandler

First we need to make the javascripts public; I did it on OS X like this:

cd public
cp /Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/WebHelpers-0.1-py2.4.egg/webhelpers/rails/javascripts/* .

Edit your autohandler like this:

templates/autohandler:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">

<html>
        <head>
                <title>Flickr!</title>
                <script src="/prototype.js" type="text/javascript" />
                <script src="/scriptaculous.js" type="text/javascript" />
                <script src="/effects.js" type="text/javascript" />
                <link rel="stylesheet" href="/flickr.css" type="text/css" media="screen" />
        </head>
        
        <body>
% m.call_next()
        </body>
</html>

This way all javascripts will be loaded and we already linked in the stylesheet we are going to make.

The Controller

Edit controller/flickr.py like this:

from imagesearch.lib.base import *
import flickrapi

flickrapi.API_KEY = "YOUR API KEY HERE"

class FlickrController(BaseController):
    def index(self):
        m.subexec('/flickr.myt')
    
    def search(self):
        photos = flickrapi.photos_search(tags=params['tags'], per_page=24)
        c.photos = [photo.getURL(size="Small", urlType='source') for photo in photos ]
        m.comp('/photos.myt')

It should be pretty straight forward, we load the flickrapi. Set the API_KEY. And define two actions in our controller. The first index just renders 'flickr.myt' with full inheritance the other search uses the flickr-api to select all photos by using the tag from ARGStags?. ARGS are given to this action by the form from flickr.myt with a POST method. It then 'partially' renders the following template by calling the Myghty function m.comp:

templates/photos.myt:

% for photo in c.photos:
        <img class="photo" src="<% photo %>">
% #end for

The Myghty Templates

We render the form in flickr.myt by making use of the  form webhelpers. The form_remote_tag comes from the  prototype helpers. A quick glance over there should give you all the information you need to understand the template.

templates/flickr.myt:

<% h.form_remote_tag(url=h.url(action="search"), 
       update="photos", 
       complete=h.visual_effect("Blind_down", "photos"), 
       loading=h.update_element_function("spinner", content="loading..."), 
       loaded=h.update_element_function("spinner", content="")) %>

<div id="spinner"></div>

<fieldset>
        <label for="tags">Tags:</label>
         <% h.text_field("tags") %>
         <% h.submit("Find") %>
</fieldset>

<div id="photos" style="dislay:none"></div>

<% h.end_form() %>

Finishing it off

Now the only thing left is giving it a nice stylesheet. I know it's cheap but all I did was use a copy of the stylesheet from the Rails screencast.

public/flickr.css:

body {
    background-color: #888;
    font-family: Lucida Grande;
    font-size: 11px;
    margin: 25px;
}

form {
    margin: 0;
    margin-bottom: 10px;
    background-color: #eee;
    border: 5px solid #333;
    padding: 25px;
}

fieldset {
    border: none;
}

#spinner {
    float: right;
    margin: 10px;
}

#photos img {
    border: 1px solid #000;
    width: 75px;
    height: 75px;
    margin: 5px;
}

We are done! Ok check your stopwatch. How long did it take you?



Powered by Pylons - Contact Administrators