Bixly How-To: integrate django with facebook – part2
In the previous entry, “Bixly How-To: integrate django with facebook – part1”, we used the Facebook Javascript SDK to provide access to the Graph API...
Flickr is one of the most popular photo management websites in the world. It can host videos as well. Flickr also provides a rich API which programmers can use to access the services Flickr provides to all its users. Several API kits for different languages are available for the developers. …
Flickr is one of the most popular photo management websites in the world. It can host videos as well. Flickr also provides a rich API which programmers can use to access the services Flickr provides to all its users.
Several API kits for different languages are available for the developers. These include Flickcurl for C, flickrj for Java, Flickr.NET for .NET, phpFlickr for PHP, flickraw for Ruby, and so on. Since Django is a Python Web framework, we need a Flickr API kit for Python. The easiest to use Python interface to Flickr is Beej’s Python Flickr API. There are other API kits available for Python but Beej’s Python Flickr API proves to have the best features and best documentation.
Step 1: We start off with the Flickr integration by applying for an API Key and Secret. We apply for a non-commercial key since we are just creating an application for this tutorial.
Step 2: We then add some basic information regarding our application.
Step 3: We obtain the API Key and Secret for our application(3.png). We store them as FLICKR_API_KEY and FLICKR_API_SECRET in our settings.py respectively.
Step 4: We then go to the Edit Authentication Flow page. We set the callback url to http://localhost:8000/flickr-callback. This is the url where users go after they authenticate to Flickr.
Step 5: We create the appriopriate page to catch the authentication callback. Note that the callback will include the parameter frob which can be used to obtain the user access token.
http://localhost:8000/flickr-callback?frob=XXXXXXXXXXXXXX-XXXXXXXXXXXXXX-XXXXX
We obtain the frob value from the URL parameters, obtain the user’s access token from the frob value, and store the access token in the session. We could also store the access token in the database. The code for views.py is shown below.
from django.shortcuts import render_to_response, redirect from django.template import RequestContext from settings import FLICKR_API_KEY, FLICKR_API_SECRET import flickrapi def index(request): if 'flickr_token' in request.session: token = True else: flickr = flickrapi.FlickrAPI( FLICKR_API_KEY, FLICKR_API_SECRET) flickr.get_token_part_one( perms='write') token = False context = { 'token': token } return render_to_response( 'index.html', context, context_instance=RequestContext(request)) def flickr_callback(request): if not 'flickr_token' in request.session: f = flickrapi.FlickrAPI( FLICKR_API_KEY, FLICKR_API_SECRET, store_token=False) frob = None token = None try: frob = request.GET['frob'] token = f.get_token(frob) request.session['flickr_token'] = token except Exception: pass return redirect('index')
The code above first checks if a flickr token is stored in the session. If not, it requires the user to authenticate and finally redirect to the index page. Otherwise, it will continue normally with token having the value of True.
Note that when you have the user’s access token, you are provided several rights to his or her account depending on the permissions allowed by the user.
Step 6: Next, we download the official Python interface to the Flickr API. We download the flickrapi-X.X.X.zip file. We extract the flickrapi folder contained inside it to our project root directory.
Step 7: Now, we are ready to use the Flickr API. To test our installation, we start the interactive Python interpreter with python manage.py shell.
import flickrapi api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXX' flickr = flickrapi.FlickrAPI(api_key) sets = flickr.photosets_getList(user_id='73509078@N00') import xml.etree.ElementTree as xml xml.dump(sets)
We use xml.dump to display the contents of the xml element. The response XML of the Flickr API is returned as an ElementTree element. We demonstrate some of the parsing abilities of the ElementTree with the following examples.
sets.attrib['stat'] #ok sets0 = sets.find('photosets').findall('photoset')[0] #we get the first photoset element stored in sets0 xml.dump(sets0) """ <photoset farm="6" id="72157626330076643" photos="16" primary="5600258215" secret="e6c7026d26" server="5149" videos="0"> <title>Reiki-weekend</title> <description><a href="http://www.lighthouseworks.nl/" rel="nofollow">www.lighthouseworks.nl/</a> </description> </photoset> """
sets0.attrib['id'] #'72157626330076643' sets0.attrib['farm'] #'6' sets0.attrib['photos'] #'16'
It’s also possible to return the responses of the Flickr API as json. We do this using f = flickrapi.FlickrAPI(api_key, format=’json’). the variable sets will contain a json string after calling sets = flickr.photosets_getList(user_id=’73509078@N00’)
Step 8: You may have noticed that we didn’t use the API secret in the last example. It’s because the API secret is required for calls which require the application to be authenticated. In other words, the app user needs to tell Flickr that the application is given access to his or her account.
In the Python interpreter, we test Flickr’s two-phase authentication.
import filckrapi api_key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXX' api_secret = 'XXXXXXXXXXXXXXXXXXX' flickr = flickrapi.FlickrAPI(api_key, api_secret) (token, frob) = flickr.get_token_part_one(perms='write') #triggers a new popup or new window
flickr.get_token_part_one() first checks the on-disk token cache if the application has already been authenticated. If it isn’t, an new Flick page is opened where the access priviledges are granted by the user.
flickr.get_token_part_two((token, frob)) stores the token in the cache and remembers it for future API calls
Step 9: The problem with our implementation of Flickr authentication in views.py is that it requires a new window to be opened just to proceed with the authentication process. Another problem is that the Flick authentication process leaves repetitive code when required in several pages. The solution to these problems is to create a custom Django view decorator which handles most of the authentication process. Notice that the code is cleaner and it only requires the view to have @require_flickr_auth decorator to ensure that the user is connected to Flickr.
from settings import FLICKR_API_KEY, FLICKR_API_SECRET from django.shortcuts import render_to_response, redirect from django.template import RequestContext import flickrapi def require_flickr_auth(view): def protected_view(request, *args, **kwargs): if 'token' in request.session: token = request.session['token'] else: token = None f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, token=token, store_token=False) if token: #check validity of the token try: f.auth_checkToken() except flickrapi.FlickrError: #set invalid token to None token = None del request.session['token'] if not token: # Redirect to Flickr for authentication # if no valid token url = f.web_login_url(perms='write') return redirect(url) return view(request, *args, **kwargs) return protected_view def flickr_callback(request): f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, store_token=False) frob = request.GET['frob'] token = f.get_token(frob) request.session['token'] = token return redirect('index') def flickr(request): token = request.session['token'] f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, token=token, store_token=False) return f @require_flickr_auth def index(request): f = flickr(request) context = {} return render_to_response('index.html', context, context_instance=RequestContext(request))
Step 10: We now try to display all of the user’s photos in each of his or her photosets in succession. We then create wrapper functions getPhotos() and getPhotosets(). The function getPhotos returns all the photos of a specified photoset via photoset ID. The function getPhotosets returns all the photosets of the user. The wrapper functions are shown below. Notice that we used attrib, find, and findall just like in our test earlier. These wrapper functions parse through the contents of the returned ElementTree element and returns only the needed data as a list.
def getPhotosets(flickr): photoset_list = flickr.photosets_getList() .find('photosets') .findall('photoset') photoset_list_array = [] for photoset in photoset_list: photoset_id = photoset.attrib['id'] photoset_title = photoset.find('title').text photoset_list_array.append({ 'id':photoset_id, 'name':photoset_title}) return photoset_list_array def getPhotos(flickr,id): photoset_photos = flickr .photosets_getPhotos(photoset_id=id) .find('photoset').findall('photo') photoset_photos_list = [] for photo in photoset_photos: photo_id = photo.attrib['id'] secret = photo.attrib['secret'] farm = photo.attrib['farm'] server = photo.attrib['server'] title = photo.attrib['title'] photo_url = 'http://farm%s.static.flickr.com/%s/%s_%s.jpg' % (farm,server,photo_id,secret) photoset_photos_list.append(photo_url) return photoset_photos_list
getPhotosets() returns all the names and IDs of all the photosets of the user in a list of the form [{‘id’:’photoset_id1’,’name’:’photoset_title1’},{‘id’:’photoset_id2’,’name’:’photoset_title2’},{‘id’:’photoset_id3’,’name’:’photoset_title3’}]
getPhotos() on the other hand returns all urls of each of the photos of a specifed photoset. It returns a list of the [“url1”,”url2”,”url3”]
We modify views.py some more to include getPhotosets() and getPhotos(). The code for views.py is shown below.
from settings import FLICKR_API_KEY, FLICKR_API_SECRET from django.shortcuts import render_to_response, redirect from django.template import RequestContext import flickrapi def require_flickr_auth(view): def protected_view(request, *args, **kwargs): if 'token' in request.session: token = request.session['token'] else: token = None f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, token=token, store_token=False) if token: #check validity of the token try: f.auth_checkToken() except flickrapi.FlickrError: #set invalid token to None token = None del request.session['token'] if not token: # Redirect to Flickr for authentication # if no valid token url = f.web_login_url(perms='write') return redirect(url) return view(request, *args, **kwargs) return protected_view def flickr_callback(request): f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, store_token=False) frob = request.GET['frob'] token = f.get_token(frob) request.session['token'] = token return redirect('index') def flickr(request): token = request.session['token'] f = flickrapi.FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, token=token, store_token=False) return f def getPhotosets(flickr): photoset_list = flickr.photosets_getList() .find('photosets') .findall('photoset') photoset_list_array = [] for photoset in photoset_list: photoset_id = photoset.attrib['id'] photoset_title = photoset.find('title').text photoset_list_array.append({ 'id':photoset_id, 'name':photoset_title}) return photoset_list_array def getPhotos(flickr,id): photoset_photos = flickr.photosets_getPhotos(photoset_id=id) .find('photoset').findall('photo') photoset_photos_list = [] for photo in photoset_photos: photo_id = photo.attrib['id'] secret = photo.attrib['secret'] farm = photo.attrib['farm'] server = photo.attrib['server'] title = photo.attrib['title'] photo_url = 'http://farm%s.static.flickr.com/%s/%s_%s.jpg' % (farm,server,photo_id,secret) photoset_photos_list.append(photo_url) return photoset_photos_list @require_flickr_auth def index(request): f = flickr(request) photosets = getPhotosets(f) output = [] for photoset in photosets: photos = getPhotos(f,photoset['id']) output.append({ 'album_name':photoset['name'], 'photo_list': photos}) context = {'output':output} return render_to_response( 'index.html', context, context_instance=RequestContext(request))
Finally, the template page should look like this:
The sample Flickr integration app we created shows all of the user’s photos in succession. There are options in the Flickr API which can limit the number of results returned by the request. There is a lot more to Flickr API and Beej’s Python Flickr API than what I have described here. Be sure to check out the documentation for all the rest of the features.
References:
In the previous entry, “Bixly How-To: integrate django with facebook – part1”, we used the Facebook Javascript SDK to provide access to the Graph API...
Let’s say you wanted to provide third-party application support for your web application. You’ll probably make an app that handles API calls, set up...
The need may arise for different versions of the same image to be used in different parts of your site. ImageKit is an app that takes care of...