Posting to the Twitter API on an admin change

Apr 07, 2009 Django

For context, I've been working on a project that involves submitted messages going through a manual review process - once they've been approved in the admin, each message should be posted to Twitter. My Twitter API script is over here, for reference.

I had originally thought I'd set up a cron job to run the posting script, and I still might go back to that if the manual review from the admin starts to take too much time. Doug Hellman suggested using signals, but after some consideration I realized that Django signals would probably be overkill - it's a little disappointing because I've never actually gotten signals working in a project. I need a use case to make me figure it out, and I thought this would be it.

Instead I was browsing some old code and realized that, oh yeah, I can put a save method in my admin class ... honestly, I'm embarrassed that I didn't think of it first - it's a no-brainer.

I just wrapped all the script code in a method:

    import MySQLdb as Database
    import base64, urllib, urllib2
    def main():
        db = Database.connect("myhost", "myuser", "mypasswd", "mydbname")
        cursor = db.cursor(Database.cursors.DictCursor)
        sql = """SELECT * FROM twitter_message WHERE approved=1 AND posted=0"""
        data = cursor.fetchall()
        username = "twitter_username"
        password = "twitter_password"
        for record in data:
            message = record["message"]
            message = message.replace(',', '')
            post_data = {'status': message}
            request = urllib2.Request('')
            request.headers['Authorization'] = 'Basic %s' % ( base64.b64encode(username + ':' + password),)
   = urllib.urlencode({'status': message})
            response = urllib2.urlopen(request) # The Response
            """ the most painful part is hacking up the response to get at the status id """
            a =
            b = a.split(',') ## convert the whole thing to a list
            c = b[30] ## hope the id is always the 30th item in the list
            d = INT(c[5:]) ## strip off first part of string, leave behind the number
            if response.code == 200 and type(d) == int:
                record_id = record["id"]
                sql = """UPDATE twitter_message posted=1, post_date=NOW(), status_id=%s WHERE id=%s""" %(d, record_id)
    if __name__ == "__main__":

Then imported it as a module and called it from the relevant

    import twitterpost
    class TweetAdmin(admin.ModelAdmin):
        def save_model(self, request, obj, form, change):
            if obj.approved: twitterpost.main()
        list_filter = ('approved',)

Note that the script is called after the - the script only acts on records that have already been marked 'approved'.

That's it. Three extra lines of code (six if you count what I added to the script).