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?