django-syncr and machine tags
django-syncr is a powerful Django app that supplies everything needed to sync your project with several web APIs. I've used it several times and I've always been amazed by the quality of the code. In this article, I'll show you how easy is to add machine tags support to the Flickr app.
Machine Tags
From flickr:
Machine tags are tags that use a special syntax to define extra information about a tag.
Machine tags have a namespace, a predicate and a value. The namespace defines a class or a facet that a tag belongs to ('geo', 'flickr', etc.) The predicate is name of the property for a namespace ('latitude', 'user', etc.) The value is, well, the value.
Like tags, there are no rules for machine tags beyond the syntax to specify the parts of a machine tag. For example, you could tag a photo with :
flickr:user=straup
flora:tree=coniferous
medium:paint=oil
geo:quartier="plateau mont royal"
geo:neighbourhood=geo:quartier
Say, for example, that you have a blog and want to use machine tags to associate flickr photos with specific posts.
Code
First of all, we need to choose a machine tag for our post entry (e.g. marcofucci:post=[post_id]) and create the get_machine_tag
method in our Post
model.
class Post(models.Model):
def get_machine_tag(self):
return "marcofucci:post=%i" % self.id
The next step is to subclass syncr.app.flickr
and add one more method: syncPhotosByMachineTag
.
import calendar
from datetime import datetime, timedelta
from syncr.app.flickr import FlickrSyncr
class AdvancedFlickrSyncr(FlickrSyncr):
def syncPhotosByMachineTag(self, machine_tags, days=1):
syncSince = datetime.now() - timedelta(days=days)
timestamp = calendar.timegm(syncSince.timetuple())
result = self.flickr.photos_search(machine_tags=machine_tags, per_page=500,
min_upload_date=timestamp)
page_count = result.photos[0]['pages']
photo_list = []
for page in range(1, int(page_count)+1):
photo_list += self._syncPhotoXMLList(result.photos[0].photo)
result = self.flickr.photos_search(machine_tags=machine_tags,
page=page+1, per_page=500, min_upload_date=timestamp)
return photo_list
Now we can synchronize our photos by a machine tag.
from path.to.your.subclass import AdvancedFlickrSyncr
flickr = FlickrSyncr('<api_key>', '<api_secret>')
photos = flickr.syncPhotosByMachineTag('marcofucci:post=', days=3)
Note that we don't have to specify the value, either marcofucci:post= or marcofucci: are perfect.
The final step is to display our photos using a templatetag.
from django import template
from syncr.flickr.models import Photo
from tagging.models import TaggedItem
register = template.Library()
class PhotosByMachineTagNode(template.Node):
def __init__(self, machine_tag, varname):
self.machine_tag, self.varname = template.Variable(machine_tag), varname
def render(self, context):
context[self.varname] = TaggedItem.objects.get_by_model(Photo,
self.machine_tag.resolve(context))
return ''
@register.tag(name="get_photos_by_machine_tag")
def get_photos_by_machine_tag(parser, token):
"""
Syntax::
{% get_photos_by_machine_tag [machine_tag] as [varname] %}
Example::
{% get_photos_by_machine_tag marcofucci:post=29 as photos %}
"""
bits = token.contents.split()
if len(bits) != 4:
raise template.TemplateSyntaxError('%s tag takes exactly three arguments'
% bits[0])
if bits[2] != 'as':
raise template.TemplateSyntaxError('third argument to %s tag must be "as"'
% bits[0])
return PhotosByMachineTagNode(bits[1], bits[3])
Now we can use it in our view.
{% load advanced_flickr %}
...
{% get_photos_by_machine_tag post.get_machine_tag as photos %}
...
In conclusion
Just few lines of code to add machine tags to our website.
Note that you could need a moderation system to avoid spam.
Links
20 April 2009