RkBlog

Hardware, programming and astronomy tutorials and reviews.

Tworzenie aplikacji Facebookowych

API Facebooka uleg艂o zmianom i zawarty w artykule opis jest nieco przestarza艂y.
Facebook to pot臋偶ny mi臋dzynarodowy serwis spo艂eczno艣ciowy. Dla programist贸w serwis ten udost臋pnia us艂ugi umo偶liwiaj膮ce m.in.:
  • Tworzenie aplikacji "Facebookowych" - wbudowanych w serwis i maj膮cych dost臋p do cz臋艣ci danych i akcji u偶ytkownika.
  • Tworzenie aplikacji desktopowych, aplikacji na urz膮dzenia mobilne zintegrowanych z serwisem i jego zasobami jak aplikacje webowe wymienione powy偶ej.
  • Integrowanie w艂asnych serwis贸w z kontami u偶ytkownik贸w w Facebooku poprzez Facebook Connect (logowanie, czy te偶 np. zapraszanie znajomych).

Wszystkie materia艂y dost臋pne s膮 na stronie developers.facebook.com. Stworzone przez programist贸w aplikacje mo偶emy znale藕膰 w katalogu aplikacji. Typowymi aplikacjami Fb s膮 quizy. U偶ytkownik wyszukuje aplikacj臋 w katalogu (lub zostaje zaproszony), przechodzi na stron臋 aplikacji, gdzie wyra偶a zgod臋 na udost臋pnienie jej cz臋艣ci swoich danych, po czy przedstawiana mu jest zawarto艣膰. Po wype艂nieniu ankiety u偶ytkownik poznaje wynik i mo偶e go opublikowa膰 w swoim Feedzie (co np. pojawi si臋 te偶 jego znajomym). Znajomi mog膮 zacz膮膰 komentowa膰 wynik, sami wype艂ni膰 ankiet臋 i por贸wnywa膰 wyniki. Podobnie jest z innymi aplikacjami (np. gry). Dobre aplikacje wci膮gaj膮 ca艂e sieci u偶ytkownik贸w.

facbk1

Aplikacje tego typu mo偶na pisa膰 w wielu j臋zykach skryptowych jak PHP, Python, Ruby, Perl, Java i wiele wi臋cej. Aplikacj臋 hostujemy na w艂asnych serwerach. Dokumentacj臋 i mas臋 innych dokument贸w znajdziemy na wiki, a pomocy szuka膰 mo偶emy na forum programist贸w. Opr贸cz kwestii czysto technicznych nale偶y uwzgl臋dni膰 tak偶e kwestie prawne jak np. zakaz przechowywania danych zwr贸conych przez API Facebooka poza list膮 dozwolonych obiekt贸w. Generalnie jest co czyta膰.

W Pythonie mo偶emy skorzysta膰 z biblioteki PyFacebook u艂atwiaj膮cej komunikacj臋 z API Facebooka, jak i dostarczaj膮ca dodatkowe komponenty dla Django usprawniajace proces tworzenia aplikacji w tym frameworku. Kod biblioteki mo偶na pobra膰 z repozytorium GIT:

git clone git://github.com/sciyoshi/pyfacebook.git
Instalacja jest standardowa - setup.py install.

Zak艂adanie nowej aplikacji po stronie Facebooka

  • Przechodzimy na Tw贸rcy Aplikacji i zezwalamy na jej u偶ycie ;) I korzystamy z opcji Set Up New Application
  • Podajemy nazw臋 aplikacji i zgadzamy si臋 z regulaminem:
    facbk2
  • Nast臋pnie podajemy dodatkowe informacje jak opis i ikony aplikacji. Ustawienia te mo偶na edytowa膰 w dowolnej chwili. Ustawieniami pod innymi kartami (menu z lewej) zajmiemy si臋 p贸藕nej.
    facbk3
  • Po zapisaniu ustawie艅 zobaczymy list臋 naszych aplikacji. Jak wida膰 przyk艂adowa aplikacja "Za艂amka" nie jest jeszcze opublikowana... musimy j膮 stworzy膰!:
    facbk4

Tworzenie aplikacji w Django z pomoc膮 PyFacebook

Je偶eli mamy ju偶 dzia艂aj膮cy serwis Django w sieci - mo偶emy dostawi膰 do niego aplikacj臋 pod Facebooka, a je偶eli nie to tworzymy wszystko od podstaw - projekt, a po tym aplikacj臋. Za艂o偶臋 偶e mamy ju偶 stworzony i skonfigurowany projekt Django i mo偶emy przej艣膰 do tworzenia aplikacji.
  • Aplikacj臋 tworzymy za pomoc膮 skryptu z PyFacebook:
    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!
    
    Plik djangofb.py mo偶emy skopiowa膰 do katalogu projektu z katalogu "bin" z pakietu PyFacebook. Ten skrypt tworzy szkielet aplikacji Django dla Facebooka oraz informuje co musimy jeszcze zrobi膰 偶eby ruszy膰 z miejsca.
  • Do settings.py dodaj zmienne FACEBOOK_API_KEY i FACEBOOK_SECRET_KEY i przypisz im warto艣ci kluczy naszej aplikacji (dost臋pne na li艣cie naszych aplikacji na Facebooku)
  • Dalej, do MIDDLEWARE_CLASSES dodajemy facebook.djangofb.FacebookMiddleware
  • I na koniec dodajemy aplikacj臋 do listy aplikacji w INSTALLED_APPS. U mnie NAZWA_PROJEKTU.zalamka
  • Teraz w urls.py dodajemy wpis dla nowej aplikacji (troch臋 go zmieni艂em ni偶 to co sugeruje djangofb):
    (r'^zalamka/', include('zalamka.urls'))
  • W odr贸偶nieniu od przyk艂adu opisanego w tutorialu PyFacebook - djangofb nie stworzy艂o w katalogu aplikacji podkatalogu "templates". Kopiujemy go z podkatalogu pakietu PyFacebook: /examples/pyfacebook_sample i w settings.py dodajemy do TEMPLATE_DIRS 艣cie偶k臋 do tego katalogu.
  • Edytujemy plik models.py naszej aplikacji i zmieniamy maxlength na max_length (bo zapewne u偶ywamy Django 1.0 lub nowsze)
  • Tworzymy tabele aplikacji:
    python manage.py syncdb
  • Je偶eli mamy publiczne IP to mo偶emy podpi膮膰 lokalny serwer deweloperski do test贸w, je偶eli nie - musimy wrzuci膰 aplikacj臋 na hosting i z niego debugowa膰 ;) W przypadku publicznego IP serwer deweloperski uruchamiamy na porcie 80 (standardowy port www, pod Linuksem wymaga膰 b臋dzie pewnie praw roota, sudo):
    python manage.py runserver 0.0.0.0:80
  • Projekt Django dost臋pny jest pod http://NASZE_IP, czyli aplikacja Facebookowa pod http://NASZE_IP/zalamka/.
  • Na Facebooku edytujemy ustawienia aplikacji i przechodzimy do zak艂adki "Strona Ramowa". Podajemy tam Canvas Callback URL czyli http://NASZE_IP/zalamka/, a tak偶e Adres URL strony ramowej - zazwyczaj nazwa aplikacji bez znak贸w specjalnych ("zalamka"), oraz Metoda renderowania ustawiamy na FBML.
    facbk5
  • Teraz pod adresem http://apps.facebook.com/NAZWA/ powinna by膰 dost臋pna nasza aplikacja (do test贸w), u mnie "NAZWA", czyli "Adres URL strony ramowej" to "zalamka":
    facbk6
    facbk7
    Przyk艂adowa zawarto艣膰 nie dzia艂a (ma wbite inne URLe) wi臋c mo偶emy od razu przej艣膰 dalej, je偶eli "wida膰" aplikacj臋 na Facebooku.
  • Zamiast ramki (iframe) wybrali艣my FBML jako spos贸b wy艣wietlania aplikacji. FBML to "Facebook Markup Language", czyli zbi贸r dodatkowych znacznik贸w umo偶liwiaj膮cych integracj臋 r贸偶nych element贸w serwisu - o czy przekonamy si臋 tworz膮c nasz膮 przyk艂adow膮 aplikacj臋.
  • Teraz trzeba przygotowa膰 zawarto艣膰 strony g艂贸wnej naszej aplikacji. W tym przyk艂adzie chc臋 wy艣wietla膰 najnowsze demoty z demotywatory.pl. Kodzik kt贸ry odwala brudn膮 robot臋 to:
    # -*- 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)
    
    Po przetestowaniu mog臋 go przenie艣膰 do widoku, a wyci膮gni臋te dane przekaza膰 do szablonu.
  • Widok mamy jeden, views.py wygl膮da tak:
    # -*- 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 zosta艂 zdemotywowany
    	if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
    		uid = request.facebook.uid
    		request.facebook.feed.publishUserAction ('21106...TUTAJ_ID_SZABLONU_WYPOWIEDZI', {'demot' : request.POST['demot']}, [], 1)
    		return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    	
    	# wy艣wietl list臋 demotywator贸w
    	
    	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})
    
    Pomi艅my na razie to co jest dla request.POST. Widzimy do艣膰 prosty kod - pobieramy stron臋 demotywatory.pl i wyci膮gamy fotki. Dla wi臋kszej wydajno艣ci pobran膮 stron臋 zapisujemy na serwerze i u偶ywamy przez 1 godzin臋:
    if isfile(cache_file) and getmtime(cache_file) > time()-3600:
    
    Pojawia si臋 tak偶e obiekt request.facebook, za pomoc膮 kt贸rego mamy dost臋p do API Facebooka odpowiednio opakowane w Pythonowe metody.
  • U偶yty szablon canvas.fbml to zwyk艂y szablon Django, w kt贸rym mo偶na (lecz nie trzeba) u偶y膰 znacznik贸w FBML. Szablon wygl膮da tak:
    <fb:header>
     Za艂amka jest wsz臋dzie. Negatywne emocje z <a href="http://demotywatory.pl">Demotywatory.pl</a> teraz na Facebooku :(
    </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="" /> To mnie zdemotywowa艂o... niech zdemotywuje innych</p>
    	
    	<fb:editor action="./" labelwidth="100">
    	<input type="hidden" value="{{ i.0 }}" name="demot" />
    	<fb:editor-buttonset>
    		<fb:editor-button value="Udost臋pnij"/>
    	</fb:editor-buttonset>
    	</fb:editor>
    	
    	</div>
    	<br /><br />
    	{% endfor %}
    	</div>
    
      {% else %}
      	 <div class="grayheader clearfix" style="text-align:center;"><b>Brak demot贸w albo co艣 strasznie si臋 zdemotywowa艂o i nie dzia艂a</b></div>
      {% endif %}
    <div style="text-align:center;">W aplikacji wykorzystano ikony z projekt贸w famfamfam oraz Tango.</div>
    </div>
    
    Tagi FBML rozpoznamy po fb:. W powy偶szym przyk艂adzie ustawiamy nag艂贸wek strony za pomoc膮 fb:header, oraz generujemy formularze poprzez fb:editor (cho膰 w tym przypadku pro艣ciej by艂oby zrobi膰 w艂asny). W efekcie wchodz膮c na stron臋 aplikacji otrzymamy:
    facbk10
  • Wy艣wietlanie listy fotek to ma艂o. W tej aplikacji chcemy 偶eby u偶ytkownik m贸g艂 dodawa膰 informacje o demotywacji do swojego profilu. Po to zosta艂 umieszczony formularz w szablonie. Za jego obs艂ug臋 w aplikacji odpowiada fragment widoku:
    # POST - user zosta艂 zdemotywowany
    	if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
    		uid = request.facebook.uid
    		request.facebook.feed.publishUserAction ('TUTAJ_ID', {'demot' : request.POST['demot']}, [], 1)
    		return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    
    Metoda feed.publishUserAction Przyjmuje kilka argument贸w: id zarejestrowanego szablonu, s艂ownik z dodatkowymi danymi jakie maj膮 by膰 przekazane do szablonu, lista ID znajomych, kt贸rych ta wiadomo艣膰 dotyczy (mo偶e by膰 puste), oraz typ wiadomo艣ci 1 - jednolinijkowa, 2 - kr贸tka.
  • Chc膮c publikowa膰 w profilu, na feedzie u偶ytkownika wiadomo艣ci nale偶y zarejestrowa膰 szablon s艂u偶膮cy do tego. Mo偶na to zrobi膰 poprzez Feed Template Console podaj膮c tekst poszczeg贸lnych typ贸w wiadomo艣ci:
    facbk8
    Zmienne umieszczane s膮 w postaci {*nazwa_zmiennej*}. Ka偶da wiadomo艣膰 musi zaczyna膰 si臋 od wbudowanej zmiennej {*actor*} wstawiaj膮cej imi臋, nazwisko autora wiadomo艣ci. Wstawiaj膮c w艂asne zmienne trzeba wstawi膰 przyk艂adow膮 warto艣膰 do JSONa w Sample Template Data poni偶ej formularza z tre艣ci膮 wypowiedzi. Po zarejestrowaniu dostamy numer ID szablonu:
    facbk9
  • Maj膮c ID szablonu mo偶emy go wykorzysta膰 do wys艂ania wiadomo艣ci. Nasza aplikacja ko艅czy si臋 na przekierowaniu u偶ytkownika na jego profil:
    request.facebook.feed.publishUserAction ('TUTAJ_ID', {'demot' : request.POST['demot']}, [], 1)
    return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    
    facbk11
Przedstawiona aplikacja jest bardzo prosta i wykorzystuje niewielki zakres API Facebooka. Tworzenie wi臋kszych aplikacji zwi臋ksza niestety czas potrzebny na testowanie i wykorzystywanie odpowiednich metod API. http://apps.facebook.com/zalamka/.
RkBlog

Django, 9 July 2009, Piotr Mali艅ski

Comment article