Example Facebook application in Django

Everything for developers can be found on developers.facebook.com. Available to users apps are located in apps directory. Usually users do some quizzes, publish their results and compare, comment with other friends.

Facebook app can be writen in many languages like PHP, Python, Ruby, Perl, Java. Apps are hosted on your server, not on facebook. APIs for all of this can be found on the wiki, and some support is available on the forum.

For python developers there is PyFacebook library, which helps in using the Facebook API, and in making Django apps integrated with the site. The code can be obtained from GIT repository:

git clone git://github.com/sciyoshi/pyfacebook.git

Go to App Developers and click on Set Up New Application

Enter a name for you app and accept the terms:

Next we can set up icons and description for the app. You can change them later.

After saving we will see a list of our apps. To make it available on Facebook - we have to make the app in Django.

To create basic app for use with Facebook use djangofb.py from PyFacebook (you can copy it to the project folder): python djangofb.py startapp zalamka Creating Facebook application 'zalamka'... Writing /home/piotr/svn/0skala/biblioteka/zalamka/models.py... Writing /home/piotr/svn/0skala/biblioteka/zalamka/views.py... Writing /home/piotr/svn/0skala/biblioteka/zalamka/__init__.py... Writing /home/piotr/svn/0skala/biblioteka/zalamka/urls.py... Done! There are a couple of things you NEED to do before you can use this app: * Set FACEBOOK_API_KEY and FACEBOOK_SECRET_KEY to the appropriate values in settings.py * Add 'facebook.djangofb.FacebookMiddleware' to your MIDDLEWARE_CLASSES in settings.py * Add 'NAZWA_PROJEKTU.NAZWA_APLIKACJI' to your INSTALLED_APPS in settings.py The final step is to add (r'^biblioteka/', include('biblioteka.zalamka.urls')) to your urls.py, and then set your callback page in the application settings on Facebook to 'http://your.domain.com/biblioteka/'. Good luck!

from PyFacebook (you can copy it to the project folder): Add to settings.py variables: FACEBOOK_API_KEY and FACEBOOK_SECRET_KEY and set your app API KEY and Secret Key (you can get if from your app list)

variables: and and set your app API KEY and Secret Key (you can get if from your app list) Add new middleware to MIDDLEWARE_CLASSES . Add facebook.djangofb.FacebookMiddleware

. Add And finaly add this django app into INSTALLED_APPS . In my case it's PROJECT_NAME.zalamka

. In my case it's Next in urls.py add rule for the new app (I use bit different than the suggestion): (r'^zalamka/', include('zalamka.urls'))

add rule for the new app (I use bit different than the suggestion): Compared to the tutorial on facebook wiki - I didn't got " templates " folder in my app, so I copied it from the example in PyFacebook package ( /examples/pyfacebook_sample ). If we have templates folder we can add it to TEMPLATE_DIRS in settings.py .

" folder in my app, so I copied it from the example in PyFacebook package ( ). If we have templates folder we can add it to in . Edit models.py of the app and change maxlength to max_length

of the app and change to Create tables: python manage.py syncdb

If you have public IP - you can use your local django development server to create and debug the app. If not - you have to push changes to the main server, and debug the app from there. For public IP we have to start the Django server on port 80, which need root/sudo permissions: python manage.py runserver 0.0.0.0:80

Then our project is available under http://Your_IP , and the facebook app in this example http://Your_IP/zalamka/ .

, and the facebook app in this example . Now edit app settings on Facebook, and go to "Canvas" tab. Set Canvas Callback URL to http://Your_IP/zalamka/ , and Canvas Page URL to "zalamka" - this is the URL-name of the app that will be use on facebook. Also change Render method to FBML .

to , and to "zalamka" - this is the URL-name of the app that will be use on facebook. Also change to . Now under http://apps.facebook.com/NAME/ you should see a basic Facebook app comming from your server: The basic app you see isn't anything useful, so it's time to make one.

In this app we are using FBML which is a set of extra HTML-like tags that allows easy integration with some facebook components (they can make forms, display comment boxes and so on).

My goal is to make an app that will show some pictures from a website demotywatory.pl (you can make the same for a lolcat site for example). The basic code that extracts the URLs and info I need looks like this: # -*- coding: utf-8 -*- from re import findall import urllib2 opener = urllib2 . build_opener () opener . addheaders = [( 'user-agent' , 'Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1' )] d = opener . open ( 'http://www.demotywatory.pl' ) de = d . read () print findall ( '<div\sclass="demot_pic"><a\shref="(.*?)"><img\ssrc="(.*?)"\sclass="demot"\salt="(.*?)"\s/></a></div>' , de )

I my "zalamka" test app I have one view: # -*- coding: utf-8 -*- from re import findall import urllib2 from os.path import isfile , getmtime , join from time import time from django.http import HttpResponse from django.shortcuts import render_to_response from models import User from django.conf import settings import facebook.djangofb as facebook @facebook.require_login () def canvas ( request ): # POST - user submitted form if request . POST and 'demot' in request . POST and len ( request . POST [ 'demot' ] . strip ()) > 0 : uid = request . facebook . uid request . facebook . feed . publishUserAction ( '21106...TEMPLATE_ID' , { 'demot' : request . POST [ 'demot' ]}, [], 1 ) return request . facebook . redirect ( request . facebook . get_url ( 'profile' , id = uid )) # show the images cache_file = join ( settings . MEDIA_ROOT , 'demotywator.cache' ) if isfile ( cache_file ) and getmtime ( cache_file ) > time () - 3600 : # use cached de = open ( cache_file ) . read () else : # get new content try : opener = urllib2 . build_opener () opener . addheaders = [( 'user-agent' , 'Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1' )] d = opener . open ( 'http://www.demotywatory.pl' ) de = d . read () cache = open ( cache_file , 'w' ) cache . write ( de ) cache . close () except : # log this de = '' demots = findall ( '<div\sclass="demot_pic"><a\shref="(.*?)"><img\ssrc="(.*?)"\sclass="demot"\salt="(.*?)"\s/></a></div>' , de ) name = request . facebook . users . getInfo ([ request . facebook . uid ], [ 'first_name' ])[ 0 ][ 'first_name' ] return render_to_response ( 'canvas.fbml' , { 'name' : name , 'demots' : demots }) request.POST for now. The rest of the code is basic - get the page and extract data. For better performance I cache the data for 1 hour: if isfile ( cache_file ) and getmtime ( cache_file ) > time () - 3600 : request.facebook which allows us to use Facebooka API mapped to Python methods.

for now. The rest of the code is basic - get the page and extract data. For better performance I cache the data for 1 hour: which allows us to use Facebooka API mapped to Python methods. Used template canvas.fbml is a Django template, in which we can (but don't have to) use FBML. In my case it looks like this: < fb:header > It's so demotivating. < a href = "http://demotywatory.pl" > Demotywatory.pl </ a > now on Facebook :( </ fb:header > < style > . demot { margin-top : 2 px ; padding : 5 px ; background-color : black ; width : 490 px ; margin-left : 10 px ; } . demot p { text-align : center ; font-weight : bold ; padding-left : 20 px ; color : yellow ; } </ style > < div class = "clearfix" style = "border: 1px #d8dfea solid; padding: 10px; width:520px;margin: 0 auto 0 auto;" > {% if demots %} < div class = "grayheader clearfix" style = "text-align:center;" > {% for i in demots %} < h3 style = "margin-bottom:3px;margin-top:15px;background-color:black;color:white;padding:5px;width:490px;margin-left:10px;" > {{ i.2 }} </ h3 > < a href = "{{ i.0 }}" >< img src = "{{ i.1 }}" alt = "{{ i.2 }}" /></ a >< br /> < div class = "demot" >< p >< img src = "http://www.python.rk.edu.pl/site_media/zalamka.png" alt = "" /> It's depressing, so I want to depress others </ p > < fb:editor action = "./" labelwidth = "100" > < input type = "hidden" value = "{{ i.0 }}" name = "demot" /> < fb:editor-buttonset > < fb:editor-button value = "Submit" /> </ fb:editor-buttonset > </ fb:editor > </ div > < br />< br /> {% endfor %} </ div > {% else %} < div class = "grayheader clearfix" style = "text-align:center;" >< b > No pictures </ b ></ div > {% endif %} < div style = "text-align:center;" > In this apps icons from famfamfam and Tango projects are used. </ div > </ div > FBML Tags start with fb: . In the template above I've set page header with fb:header , and made a HTML form with fb:editor (but I could use my own). In result I get:

is a Django template, in which we can (but don't have to) use FBML. In my case it looks like this: FBML Tags start with . In the template above I've set page header with , and made a HTML form with (but I could use my own). In result I get: Displaying content isn't enough. I want to allow users post infos about a picture on their profile/wall - for this purpose I've added the form. In the view the form is controlled by this code: if request . POST and 'demot' in request . POST and len ( request . POST [ 'demot' ] . strip ()) > 0 : uid = request . facebook . uid request . facebook . feed . publishUserAction ( 'TEMPLATE_ID' , { 'demot' : request . POST [ 'demot' ]}, [], 1 ) return request . facebook . redirect ( request . facebook . get_url ( 'profile' , id = uid )) feed.publishUserAction method takes few arg: id of registered template, dictionary with extra variable for the template, ID list of user friends to notify, and message type: 1 - one line, 2 - short.

method takes few arg: id of registered template, dictionary with extra variable for the template, ID list of user friends to notify, and message type: 1 - one line, 2 - short. To publish messages on the wall we can use templates, which need to be registered on Feed Template Console: Variables are passed in form {*name*} . Every template must start with {*actor*} , which inserts message autor name. If we use our own variables - we have to specify a test value in Sample Template Data . When we register the template we will get the template ID:

Variables are passed in form . Every template must start with , which inserts message autor name. If we use our own variables - we have to specify a test value in . When we register the template we will get the template ID: If we have the template ID we can use it to send the message. The app ends with redirecting the user to it's wall: request . facebook . feed . publishUserAction ( 'TEMPLATE ID' , { 'demot' : request . POST [ 'demot' ]}, [], 1 ) return request . facebook . redirect ( request . facebook . get_url ( 'profile' , id = uid ))

For me the APIs that Facebook provie aren't the best thing on the net. One thing that there is no nice documentation for the PyFacebook (you have to look at the standard API docs). Second - if you go see an API description - there should be real code examples (expecialy for Connect), and linkt to things I could use also (for example you can add a comment on your website with XFBML or using JS API, but the docs on the JS API won't tell you that). Third: JavaScript API? JS making queries (FQL) ? It's hard to debug, hard to integrate with server-side websites. And some browsers don't render XFBML :) For me good API can be found at Flickr - clean REST API for read and write operations with various permissions that is managed by server-side language of your site.

RkBlog