Dashboard widget to monitor dreamhost status

I’ve made a dashboard widget for OSX that monitors the dreamhost status blog. It’s very simple.

Screenshot

Snap it up here…

Widgets
Hosting

Comments (2)

Permalink

Creating iCal feeds in Django

I also wanted to add an iCal feed to my Django website. I did it like this.

In my view, I set up the mime type thusly:
response = HttpResponse(mimetype='text/calendar')

I figured that minutes and seconds were fairly unimportant for my application, and the dates would be quite happy to be Zulu (GMT), so I dodged that part up and just hard coded it, and I’m just passing the date and time below. You should get fancy in your view if you want the times to be perfectly aligned.

Then, I set up my template:
BEGIN:VCALENDAR
VERSION:2.0
NAME:mactactic.com Replacement Calendar
X-WR-CALNAME:mactactic.com Replacement Calendar
{% for md in modeldict %}BEGIN:VEVENT
URL;VALUE=URI:http://mactactic.com/detail/{{md.slug}}/
SUMMARY:End-of-life for {{md.name}}
DTSTART:{{md.replacedate|date:"Ymd"}}T000000Z
DTEND:{{md.replacedate|date:"Ymd"}}T000000Z
END:VEVENT
{% endfor %}END:VCALENDAR

Uncategorized

Comments (1)

Permalink

Country detection in Django

On my Django website mactactic.com, I needed to sus out which country a visitor was coming from.

I found MaxMind (which is a commercial product, but has a GPL’d library in C and Python), and it seemed okay… But it was beyond painful to install in a shared hosting environment. GNU configure was responsible for most of the fun, but it just felt bad & hacky. It was a huge package too, for something that’s really pretty basic.

Some Google and i stumbled across ip2cc.py, which was a totally python-native ip address to country code system. It’s got the added bonus of being independant of maxmind. It actually FTPs a list of IP delegations from IANA manually and builds it’s own database. Great!

Few issues, the ip2cc.py program is a standalone, and needed to be converted into a module. Also, it’s exception handling wasn’t as wide as I wanted in a web application, so i changed a few bits and pieces as well as converted it into a module. So now it’s error reporting is much less than adequate, it will just return a country code of ‘??’ where it can’t find it’s database file, or under any other error condition.

The country codes reported are the ones directly from the IANA database.

ip2cc (which you should download if you’re using this django hack) includes update.py, which is responsible for fetching the database. You should probably put update.py in a cron job if you use this in production once a week or so.

Next step was to integrate it with Django. I’m a slight django neophyte, but the long and the short of it:

  • Download ip2cc, run update.py and then test ip2cc
  • Check your django views in your application are using RequestContext - even if you’re using render_to_response (check the Note below)
  • Add the Context processor that’s in the blockquote below to your settings.py
  • Try out {{country}} in your template

OK, so here’s the code:

ip2ccm.py

import re, struct

is_IP = re.compile('^%s$' % r'.'.join([r'(?:(?:2[0-4]|1d|[1-9])?d|25[0-5])']*4)).match

class CountryByIP:

    def __init__(self, filename):
        self.fp = open(filename, 'rb')

    def __getitem__(self, ip):
        offset = 0
        fp = self.fp
        for part in ip.split('.'):
            start = offset+int(part)*4
            fp.seek(start)
            value = fp.read(4)
            assert len(value)==4
            if value[:2]=='xFFxFF':
                if value[2:]=='x00x00':
                    raise KeyError(ip)
                else:
                    return value[2:]
            offset = struct.unpack('!I', value)[0]
        raise RuntimeError('ip2cc database is briken') # must never reach here

import sys, os
def lookup(ip):
    db_file = '/home/myproject/ip2cc.db'  ### SET THIS UP
    try:
        db = CountryByIP(db_file)
    except IOError, exc:
        import errno
        if exc.errno==errno.ENOENT:
          return "??"
        else:
          return "??"
    try:
        cc = db[ip]
    except:
        return "??"
    else:
        return cc

Add this (or create a) context_processors.py

import yourproject.ip2ccm

def country(request):
    from django.conf import settings
    ip = request.META.get('REMOTE_ADDR')
    country = ip2ccm.lookup(ip)

    context_extras = {}
    context_extras['country'] = country
    return context_extras

And into your settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
     'yourproject.context_processors.country',
)

So, give it a bash, and let me know if it works for you, or if not.

django
python

Comments (2)

Permalink