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:
Creating new app on Facebook
- 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.
Creating a Facebook integrated Django app with PyFacebook
We need a new or existing Django project. If you create a new one - set the basic configuration like database. If your done with that we can continue.- To create basic app for use with Facebook use djangofb.py from PyFacebook (you can copy it to the project folder):
This script will make a Django app with some basic Facebook app skeleton, and also will instruct what you need to do more to make it work
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!
- 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)
- Add new middleware to MIDDLEWARE_CLASSES. Add facebook.djangofb.FacebookMiddleware
- And finaly add this django app into INSTALLED_APPS. In my case it's PROJECT_NAME.zalamka
- Next in urls.py add rule for the new app (I use bit different than the suggestion):
(r'^zalamka/', include('zalamka.urls'))
- 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.
- Edit models.py of the app and change maxlength to max_length
- 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/.
- 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.
- 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:
If it works I can move it to a Django view.
# -*- 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:
Skip 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:
# -*- 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})
New thing is also request.facebook which allows us to use Facebooka API mapped to Python methods.if isfile(cache_file) and getmtime(cache_file) > time()-3600:
- 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:
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:
<fb:header> It's so demotivating. <a href="http://demotywatory.pl">Demotywatory.pl</a> now on Facebook :( </fb:header> <style> .demot { margin-top:2px; padding:5px; background-color:black;width:490px;margin-left:10px; } .demot p { text-align:center; font-weight:bold; padding-left:20px; 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>
- 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:
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.
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))
- 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:
- 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.
Comment article