How to integrate Google Reader, Delicious.com and your blog using Django

posté le 7 janvier 2010 à 20h25 dans la catégorie DjangoGeek .

I’m a heavy user of Google Reader. I have more than 180 feeds in my listing. I’m also a heavy user of Delicious.com. I have bookmarked more than 1900 URLS since October 2005. And I have a tumblelog. Now, if I had to take a site from one of my reading on Google Reader and manually save it on my site and then manually add it to Delicious, I would become nuts in less time to say the Magic Word. But here comes Django and some library at the rescue.

So, I need an automated mechanism that will able me to post from within Google Reader to my web site and then to add this to my Delicious account at the same time. Using Django and PyDelicious, it is really easy.

The model

First, we need a model in Django that will hold the various links in your database of choice.

Here is the (simplified) model for my tumblelog (source available on bitbucket).

# models.py from the links application
class Link(models.Model):
    """A Link to a site (heavily geared towards delicious.com)"""
    LIVE_STATUS = 'L'
    DRAFT_STATUS = 'D'
    STATUS_CHOICES = (
        (LIVE_STATUS, 'Live'),
        (DRAFT_STATUS, 'Draft'),
    )

    url = models.URLField(verify_exists=False)
    title = models.CharField(blank=True, max_length=128, 
                    help_text="Description on delicious.com")
    slug = models.CharField(blank=True, max_length=128)
    description = models.TextField(blank=True, max_length=1000, 
                    help_text="extended on delicious.com")
            tags = TagField()
    posted = models.DateTimeField(blank=True, 
                        default=datetime.datetime.now,
                        help_text="dt on delicious.com.Format is ISO8601: 1984-09-01T14:21:31Z")
    status = models.CharField('status',
                          max_length=1,
                          choices=STATUS_CHOICES,
                          default=DRAFT_STATUS)

The url, title, description, tags and posted fields are directly related to the various fields you can enter on Delicious.com (url, title, notes, tags and the posted date). I also have some meta fields like the slug and the status that handle some technicalities (more on that later).

The TagField comes directly from the quasi defacto standard django apps django-tagging.

Delicious integration

The first step will be to make sure that each time I save a link, it is posted to my Delicious account. And thanks to the sleek pydelicious library, it is a breeze to do. Once you have download and install it, you should add the a DELICIOUS_USER and a DELICIOUS_PWD settings in your settings.py.

Next import the delicious API in your models.py file.

from pydelicious import DeliciousAPI

And overwrite the save method in your Link model.

# models.py from the links application
def posted_iso(self):
    """Return the posted date as an ISO8601 date"""
    iso = self.posted.isoformat()
    # replace the milliseconds by Z, to comply with delicious requirement
    pos = iso.rfind('.')
    if pos == -1:
        pos=len(iso)
    return iso[:pos] + 'Z'
posted_iso.description = 'ISO Format'

def save(self, **kwargs):
    super(Link, self).save(**kwargs)
    if self.status == self.LIVE_STATUS:
        delicious = DeliciousAPI(settings.DELICIOUS_USER, settings.DELICIOUS_PWD)

        delicious.posts_add(url=self.url,
                            description=self.title,
                            extended=self.description,
                            tags=self.tags,
                            dt=self.posted_iso(),
                            replace=True)

Nothing fancy here. Each time you save, first you call the super().save method to let Django save your entry in the database. Then, before posting it to Delicious, you need to check if the status is LIVE_STATUS. First, you don’t want to save in Delicious a draft entry. And second, it will be very handy when we will post a link from within Google Reader. If the status is indeed ‘live’, then just instantiate a DeliciousAPI object and call the posts_add method with the various field as parameters. I did use the replace=True argument to make sure I replace an existing URL in case I wanted to make, for instance, an update to the description later on (to fix typo and whatnot).

Notice that we also added a posted_iso method to convert the datetime field into proper ISO8601 date string in order to comply with the Delicious requirement.

Creating a custom ‘send to’ in Google Reader

Even if you don’t have a web site, you can already use the ‘send to’ feature of Google Reader to share links with other. Go to your Settings page and select the ‘Send To’ panel.

Settings

There, you can select the various integration already provided by Google (I have checked the Delicious, but you have quite a lot of pre-made services).

To create your own, simply click on the ‘Create a custom link’ at the bottom and enter the various information

Create Custom Link

As show on the screenshot above, you have to provide a name, a URL and an optional icon URL. For the URL, Reader provides 4 handy substitutions: the source (which is the name of the blog or site), the title of the post, the url (of course) and even a short url (for Twitter and such). For our web site, the URL will look like this http://yoursite.url/path/to/your/api/?title=${title}&url=${url}. Make sure to match the path with the one from your URLConfs.

Save it and now, when browsing Google Reader, you will have at the bottom of each post a ‘send to’ menu with the various sharing options.

Send to

Adding an API on you tumblelog

Finally, we need to hook this call from Google Reader with an API on your web site. It’s very easy, thanks to Django. First, add an url pattern to your URLConfs.

# urls.py from the links application.
from links.views import link_add

urlpatterns = patterns('',
                   # ...
                   # other stuff cut out for clarity
                   # ...
                   url(r'^api/add/$', login_required(link_add), name='link_add'),
                   )

Notice that this view is (very simply) protected from abuse with the login_required decorator.

Then add this view method.

# views.py from the links application
def link_add(request):
    url = request.GET['url']
    title = request.GET['title']

    link = Link(url=url, 
                title=title, 
                slug=slugify(title),
                status=Link.DRAFT_STATUS,
                )
    link.save()

return HttpResponseRedirect(urlresolvers.reverse('admin:links_link_change', args=(link.id,)))

It simply extracts the url and title from the GET request coming from Google Reader, creates a Link object by setting the title and url from Google Reader, populating the slug from the title and setting the status to Link.DRAFT_STATUS. Then the object is saved and the view redirect to the correct admin page, ready to be reviewed.

It is important to set the status to DRAFT_STATUS as to prevent the save method to post the link to Delicious without being reviewed and annotated via the admin first.

Conclusion

And there you have it. Browse your feed from within Google Reader. When you find something worthy, use the ‘send to’ to post this to your web site. Review it in the awesome Django admin and save it to your Delicious account, all in a couple of clicks.

My next step will be to write a javascript bookmark link to automate this from site I find outside of Google Reader. But this will be for a future post.

Commentaires (0)

Les commentaires sont maintenant fermés sur cette entrée. Si vous voulez partager une idée sur le sujet avec moi, vous pouvez me contacter directement.