Mobile web applications: Fast development with Yahoo! Blueprint, YQL and Django.

mayo 4th, 2010 § 7 comments

Today I´m going to show you how to develop a nice web application for mobile devices mixing 3 of my favourites technologies: Yahoo! Blueprint, YQL and Django.

Let me present those technologies, just in case you still don´t know:

  • Yahoo! Blueprint: is the technology we use at yahoo to rock the mobile world! Create awesome services and don´t worry about the inconveniences of a environment with lots of terminals, just write your application and we at Yahoo! will take care of everything else.
  • YQL: is the abbreviation for Yahoo! Query Language. It´s a great and powerful technology that will help you ´sqlize´web services. As their leitmotiv says "SELECT * FROM INTERNET" start using YQL, select, filter, combine different data sources with just a simple query.
  • Django: is a famous web development framework written on Python. Django will help you create easy and robust web applications using the model/template/view paradigm.

Our web application

Each time I move to a new city or I´m looking for a new home, I spend lots of hours surfing the web trying to find the perfect ´sweet home´. I´d like to search for the precious home even if I´m not in front of my computer.

Today we are going to help those flat seekers, we are going to build a mobile property finder using the Nestoria web services. Check out the Nestoria api and you will understand our YQL queries.

We will retrieve the information from the Nestoria web service using YQL and will output blueprint using the Django framework,a nice application stack to develop awesome mobile applications.

What will do our mobile web application? Easy, we will present the user a simple form asking for a location where to search, a maximun price (per week) and also the minimun number of bedrooms. Once the user enter this information we will present a list with all results found, then each item from that list will point to the original web page that contains the information for each flat. Simple, but is a nice first step, if you like you can add more information to the search form or to the presentation layer.

Getting the data with YQL

As you may know, YQL is a rocking idea from Y!, it´s a way of sqlize web services, and of course it´s open. That means we can create new tables, share them, reuse other people tables etc.

Visit http://datatables.org/, and get an idea on how many people are right now building tables for lots and lots of web services. Come on! Check the tables, experiment search parameters and data combinations in the YQL console: http://developer.yahoo.com/yql/console/

For our particular case, there is a Nestoria open table so we can use this to extract the data. Here is the table code, check it, take a look to the parameters, you can perform the same actions as using the web service.

Diving into the Yahoo! world we can find another good hint, the YOS people have created lots of libraries in lots of languages to interact with all Yahoo open services, and of courses YQL is one of those services with api. So visit the project page at github and download the yos-social python library. Follow the installation instructions and let´s try to get some flat info from YQL, try this on the python console:

PYTHON:
  1.  
  2. import yahoo.yql as yql
  3. yqlQuery = "SELECT price FROM nestoria.search WHERE place_name='Pimlico' and price_max='250' and listing_type='rent' and country='uk'"
  4. yql.YQLQuery().execute(yqlQuery)
  5. {u'query': {u'count': u'20', u'lang': u'en-US', u'updated': u'2009-08-19T10:27:47Z', u'created': u'2009-08-19T10:27:47Z', u'uri': u'http://query.yahooapis.com/v1/yql?q=SELECT+price+FROM+nestoria.search+WHERE+place_name%3D%27Pimlico%27+and+price_max%3D%27250%27+and+listing_type%3D%27rent%27', u'results': {u'listings': [{u'price': u'190'}, {u'price': u'210'}, {u'price': u'225'}, {u'price': u'190'}, {u'price': u'225'}, {u'price': u'240'}, {u'price': u'250'}, {u'price': u'103'}, {u'price': u'173'}, {u'price': u'249'}, {u'price': u'225'}, {u'price': u'225'}, {u'price': u'230'}, {u'price': u'200'}, {u'price': u'230'}, {u'price': u'185'}, {u'price': u'195'}, {u'price': u'165'}, {u'price': u'250'}, {u'price': u'195'}]}, u'diagnostics': {u'user-time': u'317', u'publiclyCallable': u'true', u'url': [{u'content': u'http://datatables.org/alltables.env', u'execution-time': u'4'}, {u'content': u'http://www.datatables.org/nestoria/nestoria.search.xml', u'execution-time': u'6'}, {u'content': u'http://api.nestoria.co.uk/api?action=search_listings&encoding=xml&has_photo=1&place_name=Pimlico&price_max=250&listing_type=rent&page=0&number_of_results=20', u'execution-time': u'293'}], u'service-time': u'303', u'build-version': u'2579'}}}
  6.  

Cool, so we can get the info in a easy way.

Creating our application with Django

The application we are going to build is not much different than other web application, we will just add a couple of tricks to help with the Blueprint development. In following lines, I´m basically going to follow a hello world tutorial in Django, we will use the model/template/view paradigm to create our output, but instead of being classic html we are going to output Yahoo! Blueprint :D

Let´s start creating a new django project, for this example i will use the version 1.1 of django framework:

CODE:
  1.  
  2. django-admin.py startproject sweethome
  3.  

Ok, if you are not familiar with a django project you will have a new ´sweethome´directory with the content:

  • __init__.py : Python module definition file.
  • settings.py : Configuration file for our application.
  • urls.py : Urls template mapping definitions.
  • manage.py : Command line script that will help you to interact with Django.

Our next step is configure our project, we are not going to deal with databases, and of course we are not going to apply fine tunning for this application. Just two settings:

  • Specifying the templates folder: We are going to use the Django template system, create a folder at the same level that the rest of your project files named ´templates´, edit the settings.py file, locate the config key TEMPLATE_DIRS and add the full path to your new ´templates´folder.
  • Telling Django how to output blueprint: The Yahoo! Blueprint technology requires that the content type that returns our application must be 'application/x-blueprint+xml'. We can specify this globaly for our project with the following option in our settings file (settings.py): DEFAULT_CONTENT_TYPE = 'application/x-blueprint+xml'

Good, seems the configuration is ready, lets code a bit.
Inside a project there may exists different django applications that perform different tasks inside our projects, in our example we just need one application that will be in charge of finding that fantastic flat for us. Let´s create an application using the command line script helper, type:

CODE:
  1.  
  2. python manage.py startapp bpsweethome
  3.  

And this will create the directory bpsweethome with the content:

  • __init__.py : Again a python module definition
  • models.py: A file where store our models, classes, form definitions, etc.
  • views.py: File where we will hold the view logic of our application.
  • test.py: Python module where you should write your applications tests cases.

Now we are going to build our application´s model, we won´t need any kind of integration with database, our simple application just show a form to search by tree fields (location, minimun bedrooms and maximun price). So our model will be compount just by a function to retrieve the information with the given input, and the form definition, take a look at our file models.py:

PYTHON:
  1.  
  2. from django.db import models
  3. from django import forms
  4. import yahoo.yql as yql
  5.  
  6. class SearchForm(forms.Form):
  7.     """
  8.     This class represents and validates the search form
  9.     """
  10.     location = forms.CharField()
  11.     max_price = forms.IntegerField()
  12.     min_beds = forms.IntegerField()
  13.  
  14.     def searchProperties(form):
  15.         """
  16.         Receives a validated form and perform the nestoria
  17.         search.
  18.         """
  19.         #Get the data from the input and build the YQL expression
  20.         data = form.cleaned_data
  21.         yqlQuery = """SELECT * FROM nestoria.search WHERE place_name='%s' and price_max='%s' and bedroom_min='%s' and has_photo='1' and listing_type='rent'""" % (data['location'], data['max_price'], data['min_beds'])
  22.  
  23.         response = yql.YQLQuery().execute(yqlQuery)
  24.  
  25.         results = list()
  26.  
  27.         #Check YQL response
  28.         if 'query' in response and 'results' in response['query'] and response['query']['results'] and 'listings' in response['query']['results']:
  29.             results = response['query']['results']['listings']
  30.  
  31.         return results
  32.  

Simple, isn´t? And our view.py is so simple? Yes it its, in this file we will place the actions that will handle the user petitions against our application. And cause our application is very simple we just have to handle two actions: the access to the search form (entry point to the application), and the listing results. Here it is our view.py:

PYTHON:
  1.  
  2. from django.shortcuts import render_to_response
  3. from sweethome.bpsweethome.models import SearchForm, searchProperties
  4.  
  5. def index(request):
  6.     """
  7.     Handles the entry point to the widget.
  8.     """
  9.     return render_to_response('index.bp', {})
  10.  
  11. def search(request):
  12.     """
  13.     Handle search post petition
  14.     """
  15.     #Only process post petitions
  16.     if request.method == 'POST':
  17.         form = SearchForm(request.POST)
  18.         if form.is_valid():
  19.             #Ok now we know the data provided by the user is valid, so perform the query
  20.             try:
  21.                 search_results = searchProperties(form)
  22.                 return render_to_response('listing.bp', {'results' : search_results})
  23.             except Exception ,e:
  24.                 pass
  25.             return None
  26.     else:
  27.         #Get request, return to the page
  28.         form = SearchForm()
  29.  
  30.     return render_to_response('index.bp', {'form' : form})
  31.  

As you can see our two actions will redirect our user to the proper template with the correct data, in case of the search action, we will check the form and return the user to the listing result template or again to the search action template (in this case, with error messages).

The last step in our Django application is tell the framework how are we going to manage the url and which actions should happend when we access certain urls. This task is done in the urls.py file, take a look to our application urls.py:

PYTHON:
  1.  
  2. from django.conf.urls.defaults import *
  3. from django.conf import settings
  4.  
  5. # Uncomment the next two lines to enable the admin:
  6. from django.contrib import admin
  7. admin.autodiscover()
  8.  
  9. urlpatterns = patterns('',
  10.  
  11. (r'^sweethome/$', 'sweethome.bpsweethome.views.index'),
  12. (r'^sweethome/index.bp$', 'sweethome.bpsweethome.views.index'),
  13. (r'^sweethome/search.bp$', 'sweethome.bpsweethome.views.search'),
  14. )
  15.  

It´s easy to read, we map web urls to actions into our views functions.

Coding Yahoo! Blueprint

Now is the time for Blueprint. We will have two templates, the search form template, that will be our entry point to the application and the listing page results. As you saw before, on the view declarations, we will have to files: index.bp and listing.bp located in the templates directory we defined on the settings.py file with the following content:

index.pb

XML:
  1.  
  2. <page>
  3.         <models>
  4.                 <model id="search">
  5.                         <instance>
  6.                                 <data xmlns="">
  7.                                         <location/>
  8.                                         <max_price/>
  9.                                         <min_beds/>
  10.                                 </data>
  11.                         </instance>
  12.                         <submission method="urlencoded-post" resource="search.bp"/>
  13.                 </model>
  14.         </models>
  15.         <page-header>
  16.                 <masthead>
  17.                         <layout-items>
  18.                                 <block class="title">Find your home sweet home</block>
  19.                         </layout-items>
  20.                 </masthead>
  21.         </page-header>
  22.         <content>
  23.                         <module>
  24.                                 <input model="search" ref="location">
  25.                                         <label>Find in: {% if form and form.location.errors %}(required){% endif %}</label>
  26.                                 </input>
  27.                                 <select1 ref="max_price" model="search" appearance="popup">
  28.                                         <label>Max price:</label>
  29.                                         <item>
  30.                                                 <value>300</value>
  31.                                                 <label>300 pounds p.w.</label>
  32.                                         </item>
  33.                                         <item>
  34.                                                 <value>500</value>
  35.                                                 <label>500 pounds p.w.</label>
  36.                                         </item>
  37.                                         <item>
  38.                                                 <value>800</value>
  39.                                                 <label>800 pounds p.w.</label>
  40.                                         </item>
  41.                                         <item>
  42.                                                 <value>1200</value>
  43.                                                 <label>1200 pounds p.w.</label>
  44.                                         </item>
  45.                                 </select1>
  46.                                 <select1 ref="min_beds" model="search" appearance="popup">
  47.                                         <label>Min bedrooms:</label>
  48.                                         <item>
  49.                                                 <value>0</value>
  50.                                                 <label>Studio</label>
  51.                                         </item>
  52.                                         <item>
  53.                                                 <value>1</value>
  54.                                                 <label>1 bedroom</label>
  55.                                         </item>
  56.                                         <item>
  57.                                                 <value>2</value>
  58.                                                 <label>2 bedrooms</label>
  59.                                         </item>
  60.                                         <item>
  61.                                                 <value>3</value>
  62.                                                 <label>3 bedrooms</label>
  63.                                         </item>
  64.                                 </select1>
  65.                                 <submit model="search">
  66.                                         <label>Search</label>
  67.                                 </submit>
  68.                                 <display-ad>
  69.                                         <banner resource="http://s.uk.nestoria.nestimg.com/i/realestate/uk/en/pb.png"/>
  70.                                         <load event="activate" resource="http://www.nestoria.co.uk"/>
  71.                                 </display-ad>
  72.                         </module>
  73.         </content>
  74. </page>
  75.  

As you may note, blueprint is a nice markup language, easy to read and write and based on xforms. What do we have in our first welcome page? First the model with the form declaration, and after that you can see how we define the form components. Note just a simple piece of django templates language:
{% if form and form.location.errors %}(required){% endif %}

If we found errors on the form validation we will come back to this blueprint page showing the error messages.

Now let´s take a look to the listing.bp:

XML:
  1.  
  2. <page>
  3.         <page-header>
  4.                 <masthead>
  5.                         <layout-items>
  6.                                 <block class="title">Found {{ results|length }} properties</block>
  7.                         </layout-items>
  8.                 </masthead>
  9.         </page-header>
  10.         <content>
  11.                         <module>
  12.                                 {% for result in results %}   
  13.                                         <placard layout="card">
  14.                                                 <layout-items>
  15.                                                         <image resource="{{result.thumb_url}}"/>
  16.                                                         <block class="title">{{result.title}}</block>
  17.                                                         <block>
  18.                                                                 <span class="subdued">{{result.summary}}</span>
  19.                                                         </block>
  20.                                                         <block class="small positive">{{result.price_formatted}}</block>
  21.                                                 </layout-items>
  22.                                                 <load event="activate" resource="{{result.lister_url}}"/>
  23.                                         </placard>
  24.                                 {% endfor %}
  25.                                 <display-ad>
  26.                                         <banner resource="http://s.uk.nestoria.nestimg.com/i/realestate/uk/en/pb.png"/>
  27.                                         <load event="activate" resource="http://www.nestoria.co.uk"/>
  28.                                 </display-ad>
  29.                         </module>
  30.         </content>
  31. </page>
  32.  

Simple again, isn´t it? We build a skeleton with blueprint (page, header, module, etc) and the we loop over the results the model will give us the list formated:
{% for result in results %}
...
{% endfor %}

Taking a look to our application

Ok, now it´s time to take a look to our little child. We can perform the first tests taking a look to the blueprint output. Using Django que can invoke the embed browser and have it running quickly, just use the helper command:

CODE:
  1.  
  2. python manage.py runserver
  3.  

And as you may note in the output you will have a development server running at you local machine.

This first approach can be usefull to get your desired blueprint output, but as you many know, Yahoo servers will query your application and then will transform that blueprint to the a specific and optimized markup for each language.
What do we have to do in order to tell Yahoo where is our application? We just need to deploy our mobile application into Yahoo! servers. Please read the Yahoo! Blueprint documentation to take a better understanding of the process, but basically these are the steps we are going to follow:

  • Download the Blueprint SDK ( http://mobile.yahoo.com/devcenter/downloads ).
  • Unzip the file, and search for a directory called Template.
  • Inside that directory you will find:
    • gallery.xml : Placer where you can put a description of you application. This will help other people find your application.
    • config.xml: Here you will specify some configuration parameters, the more important are:
      • indentifier: This identifier should be unique for each application you will deploy in Yahoo!
      • widget: In the attribute base you have to specify the URL where you are serving you blueprint application
  • Once you have everything configure pack the Template directory into a zip file.
  • Visit the url http://mobile.yahoo.com/devcenter/manage, loging and create a new project.

Once you click on the create new project you will find a form to upload your zip descriptor. Come on, upload it!! After this process Yahoo! will provide you an url like xxxx.bpapps.com. That is your end point to the mobile world, just visit that url with your mobile!

I almost forget this, yes, you have the code here:
http://github.com/arcturus/sweethome

And of course you can try it with your mobile phone or browser here:

http://sweethome.ardeenelinfierno.com

Almost forgot again! Yes, some screenshots :P


Tagged , , , ,

§ 7 Responses to Mobile web applications: Fast development with Yahoo! Blueprint, YQL and Django."

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *


dos × 2 =

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*
To prove you're a person (not a spam script), type the answer to the math equation shown in the picture. Click on the picture to hear an audio file of the equation.
Click to hear an audio file of the anti-spam equation

What's this?

You are currently reading Mobile web applications: Fast development with Yahoo! Blueprint, YQL and Django. at arde en el infierno.

meta