Back
May 12, 2010

Twitter API, OAuth and decorators

In my current project I had a task to use twitter API. Twitter uses OAuth for authentication, which is pretty dreary. To avoid fiddling with it all the time, I've moved authentication to decorator, now it looks like this:

@twitter_api
def tweet_hello(request, api):
    api.update_status('hello')
# ...

Decorator checks if key is available, and, if needed - initiates authentication. User is redirected to twitter, grants permission and is redirected back to site, to the same place where he left off. If key is available - nothing happens, just view is launched as usual.

It's convenient that there's no need for additional twitter settings in user profile.

tweepy is used as an API wrapper.

def twitter_api(view):
    def wrapped(request, args, *kwargs):
        callback_url = absolute_url(oauth_endpoint)
        auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, callback_url)

        if 'twitter_access_token' in request.session:
            key, secret =     request.session['twitter_access_token']
            auth.set_access_token(key, secret)
            return view(request, api=tweepy.API(auth), *args, **kwargs)

        request.session['twitter_action'] = request.path
        redirect_url = auth.get_authorization_url()
        request.session['twitter_request_token'] = (auth.request_token.key, auth.request_token.secret)
        return redirect(redirect_url)

    return wrapped


def oauth_endpoint(request):
    callback_url = absolute_url(oauth_endpoint)
    auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET, callback_url)
    key, secret = request.session.pop('twitter_request_token')
    auth.set_request_token(key, secret)
    verifier = request.REQUEST.get('oauth_verifier')
    auth.get_access_token(verifier)
    request.session['twitter_access_token'] = (auth.access_token.key, auth.access_token.secret)
    return redirect(request.session.pop('twitter_action'))
  • of course, you need to wrap everything in try..except blocks and process errors accordingly
  • absolute_url should return full url, with http://
  • apart from request.path you can also store POST and GET.
  • path can be passed as an argument to callback_url

Subscribe for the news and updates

More thoughts
Aug 27, 2024Technology
An Effective Preparation Algorithm for ISTQB Certification

This article offers key insights into the ISTQB certification and shares a proven preparation strategy to help candidates succeed.

Dec 8, 2022Technology
How to create a route finder on an SVG map

In one of our recent projects, we had an interesting case: the whole application was built around an interactive map for a fairly large shopping mall, and the main goal of the system was to plot the closest route to a user-selected destination.

Jun 27, 2018Technology
How to Work With Legacy Code: Code Refactoring Techniques

In this article we'll review general approach to working with the best kind of projects - the ones with old untested and undocumented spaghetti code and a tight schedule. We'll review anger management techniques, coping mechanisms and some refactoring tips that might come in handy.

May 26, 2017Technology
Tutorial: Django User Registration and Authentication

In this beginners friends article I'll explain how to make authentication with Google account on your Django site and how to make authentication for you REST API.

Oct 11, 2010Technology
Char search in Emacs as in Vim

In VIM there is a command for char search: f. After first use it can be repeated with ;. I like to navigate in line with it. You see that you need to go to bracket in a middle of a line - you press f( and one-two ; and you are there. There's no such command in Emacs, so I had to write my own. I've managed even to implement repetition with ;.

Sep 23, 2010Technology
Dynamic class generation, QuerySetManager and use_for_related_fields

It appears that not everyone knows that in python you can create classes dynamically without metaclasses. I'll show an example of how to do it.So we've learned how to use custom QuerySet to chain requests:Article.objects.old().public()Now we need to make it work for related objects:user.articles.old().public()This is done using use_for_related_fields, but it needs a little trick.