= Integrating Flickr With Django = Seeing as how flickr photostreams are the hot thing in blogs these days, I thought I might share one way of doing so that is robust. The following code will need a model that will hold various flickr bits of information that you'll use to build the URLs for your photos. The synchronize method synchronizes your flickr stream with your database, reducing unneeded Before we start, you'll need the following flickr information: * [http://www.flickr.com/services/api/keys/ API key] * Your user id. This looks something like "12345678@N00". == Set Up == I organized my project like so, but you can set up yous any way you want, as long as you modify my code samples to match. {{{ project/ __init__.py apps/ __init__.py photos/ __init__.py models.py ... lib/ __init__.py templates/ manage.py settings.py urls.py }}} You'll need Michele Campeotto's excellent !FlickrClient libraries, [http://micampe.it/things/flickrclient available for download here]. Unzip it and place "!FlickrClient.py" and "xmltramp.py" in your "lib" folder (or wherever you want to store them. Storing them inside your app is fine, too.): {{{ project/ ... lib/ __init__.py FlickrClient.py xmltramp.py ... }}} == Photos App == Knowing only a few bits of flickr's data for your photos allows you a wide array of options when creating URLs. You can specify the photo size, create links to the photo's flickr page, etc. You can read more about the URLs on [http://www.flickr.com/services/api/misc.urls.html flickr's URL documentation page]. This makes our model a snap. We only have to store four small strings of flickr data in our model, or five if you want to include the title, which I do here. You can set up your model in most any way, as long as you have the four flickr-specific models. Here's how my "photos/models.py" code looks: {{{ #!python from django.db import models from project.lib.FlickrClient import FlickrClient class Photo(models.Model): title = models.CharField(blank=True, maxlength=100) flickr_id = models.IntegerField() flickr_owner = models.CharField(maxlength=20) flickr_server = models.IntegerField() flickr_secret = models.CharField(maxlength=50) class Admin: list_display = ('title',) def __str__(self): return self.title def get_absolute_url(self): return "/photos/%s/" % (self.id) }}} == Synchronization Function == Easy enough so far, right? Now, we'll need the actual synchronization code. Add the following function to your "photos/models.py" file, adding your flickr key and user ID where needed: {{{ #!python def sync_flickr_photos(*args, **kwargs): API_KEY = 'your_api_key_here' USER_ID = 'your_id_here' cur_page = 1 # Start on the first page of the stream paginate_by = 20 # Get 20 photos at a time dupe = False # Set our dupe flag for the following loop client = FlickrClient(API_KEY) # Get our flickr client running while (not dupe): photos = client.flickr_people_getPublicPhotos(user_id=USER_ID, page=cur_page, per_page=paginate_by) for photo in photos: try: row = Photo.objects.get(flickr_id=photo("id"), flickr_secret=photo("secret")) # Raise exception if photo doesn't exist in our DB yet # If the row exists already, set the dupe flag dupe = True except ObjectDoesNotExist: p = Photo( title = photo("title"), flickr_id = photo("id"), flickr_owner = photo("owner"), flickr_server = photo("server"), flickr_secret = photo("secret") ) p.save() if (dupe or photos("page") == photos("pages")): # If we hit a dupe or if we did the last page... break else: cur_page += 1 }}} ''(Note: I know there's probably a million better ways to do this (esp. in regards to raising exceptions on "success"). You'll also want to include proper error catching. I'm no Python expert yet, so I took the easy route. Feel free to improve the code, but keep it simple.'' == The Rest == I'll leave the rest of this up to you: * You'll need to run the sync_flickr_photos function at a reasonable interval. Don't flood flickr with API calls every time someone view's your page. For instance, I use signals and the dispatcher to raise a signal whenever someone visits my photos page. If it's been more than 15 minutes since the last time I synchronized, I run the function. * To actually do anything useful with your flickr information, you'll need to create methods that build the URLs. Here's how I get a URL to a small picture (240px on longest side): {{{ #!python def get_med_pic_url(self): return "http://static.flickr.com/%s/%s_%s_m.jpg" % (self.flickr_server, self.flickr_id, self.flickr_secret) }}} * And of course, you'll have to do all the views and templates yourself. But that's the easy part!