December 9, 2010

Parsing tweets links, users and hash tags with django and python-twitter.

Hello again. Today I'm going to continue my previous post concerning django and twitter. Last time we've finished after synchronising with twitter. This time I'm gonna show you how to parse list of received tweets for rendering it in our template so that links,hash tags and users mentions are treated as clickable links. So here's the code, I've added some comments to clarify what we're doing currently:

def parse_tweets(tweets):
    import re
    
    result = []
    for tw in tweets:
        tweet = tw.text;
        #compile regexes as objects
        hash_regex = re.compile(r'#[0-9a-zA-Z+_]*',re.IGNORECASE) 
        user_regex = re.compile(r'@[0-9a-zA-Z+_]*',re.IGNORECASE)
        
        #first deal with links. Any http://... string change to a proper link
        tweet = re.sub('http://[^ ,]*', lambda t: "%s" % (t.group(0), t.group(0)), tweet)
        
        #for all elements matching our pattern...
        for usr in user_regex.finditer(tweet):
            
            #for each whole match replace '@' with ''
            url_tweet = usr.group(0).replace('@','')

            #in tweet's text replace text with proper link, now without '@'
            tweet = tweet.replace(usr.group(0),
                ''+usr.group(0)+'')

        #do the same for hash tags
        for hash in hash_regex.finditer(tweet):
            url_hash = hash.group(0).replace('#','%23')
            if len ( hash.group(0) ) > 2:
                tweet = tweet.replace(hash.group(0),
                    ''+hash.group(0)+''); 

        #append each tweet to our list. Here I'm creating a dict containing tweet's text and date
        posts.append({'tweet': tweet, 'date': s.pub_time})   
    return posts

And now to show it in template :

    {% for t in tweets %}

  • {% for k, v in t.items %}
    {% ifequal k 'summary' %}
    {{ v|safe }}
    {% else %}
    {% ifequal k 'date' %}
    {{v|timesince}} ago
    {% endifequal %}
    {% endifequal %}
    {% endfor %}
  • {% endfor %}
Probably there are better ways of doing this, but this one works for me. If you have any questions just write a comment or follow me via twitter

December 8, 2010

Check object's parameter value in django template

I'm just finishing probably the most complexed project I'll ever build in django, at least by myself. During the development I've encountered numerous problems, some of without satisfying solutions on the web. So now for the next few posts I will share the results of my research, thinking and developing. Topic for today is :

How to check value of object's parameters in a template ?

Why do I ever need to do this kind of thing you may think. Yeah that's what I thought till now. But just think of my exact example - We have a site with some objects, that people can vote on. If someone has already voted we show him the result - if not, we render a voting button. Things are easy when rendering static page that is refreshed after each vote. But what if we need (just as I did) it to be dynamic ? I'm pretty sure that this problem can be solved using custom templatetag. But I've thought about a simpler solution using filters. So let's start.
I have created a context processor storing IP address of user. In my template I'm returning list of objects in a for loop, and on each object I'm using my filter, with IP as parameter:

{{ submission|check_voting:IP_ADDRESS|safe }}

And now the filter part :

@register.filter
def check_voting(obj, ip):
    result = obj.check_vote(ip)
    if result:
        result = "
%s votes
" % obj.votes else: result = "" % (settings.SITE_URL, obj.get_absolute_url() ) return result

As you can see my filter takes two arguments - object on which it was called, and ip. Then I'm doing some processing on my object's method 'check_vote' that returns me boolean value depending on query result for vote by ip. According to it's value I'm either showing a facebook like button used for voting, or just plain vote counter.
Hope you'll find this useful.