First things first, head over to http://dev.twitter.com/apps/new, login and start filling out the form to create your app. Since this app isn't really going to be for public use, there's several fields you don't really need to worry about. Just be sure to select "browser" for the Application Type, and depending on your intentions you'll likely only need to select "Read-only" for the Default Access type.
Take note of the consumer key, consumer secret, and the access token and access token secret - the last two of which can be found by clicking on the "My Access Token" button. We'll be adding all of these to our django project's settings file in the next step. The access token and secret have been provided by twitter specifically for users who only require to interact with the twitter account behind the app, which in turn removes a step from the authentication process (yay!).
Now lets create our simple django app to house our template tags and a small utility module. I'm calling my app "django_twitter" (original I know), and we'll set up the directory like so:
mkdir django_twitter
cd django_twitter
touch __init__.py
touch latest_tweets.py
mkdir templatetags
touch templatetags/__init__.py
touch templatetags/twitter.py
Before we go any further, you'll want to add the twitter app keys and secrets from above to your project's settings.py file along with a key name for caching your timeline to:
DJANGO_TWITTER_CONSUMER_KEY = "xxxxx"
DJANGO_TWITTER_CONSUMER_SECRET = "xxxxx"
DJANGO_TWITTER_ACCESS_TOKEN = "xxxxx"
DJANGO_TWITTER_ACCESS_TOKEN_SECRET = "xxxxx"
DJANGO_TWITTER_CACHE_KEY = "django_twitter_timeline"
While you're in the settings, don't forget to add our new app to the INSTALLED_APPS.
We'll also need to snag the python oauth2 package, which you can find forked all over github. As far as I know this version is based off of the oauth package by Leah Culver and has had multiple contributors since. At the time of this writing oauth2 doesn't appear to be listed on pypi.
Returning to our app, lets open latest_tweets.py and insert the following:
import calendar, time
from datetime import datetime
from django.conf import settings
from django.core.cache import cache
import simplejson as json
import oauth2 as oauth
CONSUMER_KEY = getattr(settings, "DJANGO_TWITTER_CONSUMER_KEY")
CONSUMER_SECRET = getattr(settings, "DJANGO_TWITTER_CONSUMER_SECRET")
OAUTH_TOKEN = getattr(settings, "DJANGO_TWITTER_ACCESS_TOKEN")
OAUTH_SECRET = getattr(settings, "DJANGO_TWITTER_ACCESS_TOKEN_SECRET")
CACHE_KEY = getattr(settings, "DJANGO_TWITTER_CACHE_KEY", "django_twitter_timeline")
def oauth_req(url, http_method="GET", post_body=None, http_headers=None):
consumer = oauth.Consumer(key=CONSUMER_KEY, secret=CONSUMER_SECRET)
token = oauth.Token(key=OAUTH_TOKEN, secret=OAUTH_SECRET)
client = oauth.Client(consumer, token)
resp, content = client.request(
url,
method=http_method,
body=post_body,
headers=http_headers
)
return content
def get_tweets():
statuses = json.loads(oauth_req('http://api.twitter.com/1/statuses/user_timeline.json'))
tweets = []
get_datetime = lambda x: datetime(*(time.localtime(calendar.timegm(time.strptime(x, '%a %b %d %H:%M:%S +0000 %Y')))[0:6]))
for status in statuses:
tweet = {}
tweet["text"] = status.get("text", "")
try:
tweet["created_at"] = get_datetime(status.get("created_at", ""))
except:
tweet["created_at"] = ""
tweets.append(tweet)
cache.set(CACHE_KEY, tweets)
return tweets
if __name__ == "__main__":
get_tweets()
Most of this is relatively self explanatory. The oauth_req method is one available from the oauth docs and the get_tweets function simply uses the information from our twitter app to request the timeline in JSON format. We then parse the JSON by creating a list of tweet objects which contain the message and date (converted from UTC into a local time datetime object). Finally the new set of tweets is written into the cache which we'll use later in our template tag.
You'll note the familiar if __name__ == "__main__" at the end of the module. I've included this because our cron job we'll be creating later is going to be calling latest_tweets.py to refresh the twitter timeline in the site's cache.
Opening the templatetags/twitter.py file we can paste the following:
from django.core.cache import cache
from django import template
from django.template import Library, Node
from django.template.defaultfilters import stringfilter
from django.utils.safestring import mark_safe
from django.conf import settings
from django_twitter import latest_tweets
register = Library()
CACHE_KEY = getattr(settings, "DJANGO_TWITTER_CACHE_KEY", "django_twitter_timeline")
class TweetListNode(Node):
"""
use:
{% get_tweet_list <count> as <varname> %}
example:
{% get_tweet_list 3 as tweets %}
{% for tweet in tweets %}
{{ tweet.text|twitterize}} - {{ tweet.created_at|date:"M d, Y" }}
{% endfor %}
"""
def __init__(self, parser, token):
tokens = token.contents.split()
if len(tokens) != 4:
raise template.TemplateSyntaxError("%r requires exactly three arguments" % tokens[0])
if tokens[2] != "as":
raise template.TemplateSyntaxError("Third argument in %r tag must be 'as'" % tokens[0])
self.count, self.list_name = tokens[1], tokens[3]
def render(self, context):
tweet_list = cache.get(CACHE_KEY) or latest_tweets.get_tweets()
context[self.list_name] = tweet_list[:int(self.count)]
return ''
def get_tweet_list(parser, token):
return TweetListNode(parser, token)
get_tweet_list = register.tag(get_tweet_list)
#@register.filter
#@stringfilter
def twitterize(value, autoescape=None):
from django.utils.html import urlize
import re
# Link URLs
value = urlize(value, nofollow=False, autoescape=autoescape)
# Link twitter usernames prefixed with @
value = re.sub(r'(\s+|\A)@([a-zA-Z0-9\-_]*)\b',r'\1<a href="http://twitter.com/\2">@\2</a>',value)
# Link hash tags
value = re.sub(r'(\s+|\A)#([a-zA-Z0-9\-_]*)\b',r'\1<a href="http://search.twitter.com/search?q=%23\2">#\2</a>',value)
return mark_safe(value)
twitterize.is_safe=True
twitterize.needs_autoescape = True
twitterize = stringfilter(twitterize)
twitterize = register.filter(twitterize)
The twitterize filter is courtesy of thomasw on djangosnippets.
Our template tag will accept a count and the variable name which the context will store the tweets in.
An example of its usage can be seen in the docstring of the code example above in conjunction with the twitterize and date filters.
The final and easiest step is to add a cron job to our contab to automate the caching. If you aren't already using one of the many caching options available to django, then I'd highly suggest you get to it! Caching will increase your site's performance by an extremely noticeable amount, and in the context of this example prevent your possibly high traffic site from exceeding your app's maximum number of hourly requests allowed by twitter.
If you're using webfaction or a similar host, you can edit your conjobs by typing crontab -e while in an SSH session. My cron job looks something like this:
15,45 * * * * PYTHONPATH=/home/user/webapps/django; /home/user/webapps/django/lib/python2.5 DJANGO_SETTINGS_MODULE=myproject.settings /usr/local/bin/python2.5 /home/user/webapps/django/lib/python2.5/django_twitter/latest_tweets.py > /dev/null 2>&1
This particular cron job will run the latest_tweets.py twice every hour.
And that's it! You should have a fully functioning twitter application to use in your next django powered website!
Comments have been closed for this post.