# Copyright (c) 2007, Justin Bronn # All rights reserved. # # Released under New BSD License # """ This module contains example models for the MaxMind(R) free geolocation datasets, specifically, GeoLite Country and City: http://www.maxmind.com/app/geolitecity http://www.maxmind.com/app/geoip_country To search for IP addresses requires long integers, however, Django does not yet support these fields. These models require the BigIntegerField patch by Peter Nixon: http://code.djangoproject.com/attachment/ticket/399/django-bigint-20070712.patch """ from django.contrib.gis.db import models import re ipregex = re.compile(r'^(?P\d\d?\d?)\.(?P\d\d?\d?)\.(?P\d\d?\d?)\.(?P\d\d?\d?)$') def ip2long(ip): "Converts an IP address into a long suitable for querying." m = ipregex.match(ip) if m: w, x, y, z = map(int, [m.group(g) for g in 'wxyz']) ipnum = 16777216*w + 65536*x + 256*y + z return ipnum else: raise TypeError, 'Invalid IP Address: %s' % ip class IPManager(models.GeoManager): def ipquery(self, ip): "Returns any LocationBlocks matching the IP query." num = ip2long(ip) # Using select_related slows down this query a lot qs = self.get_query_set().filter(ipfrom__lte=num).filter(ipto__gte=num) if len(qs) == 1: return qs[0] else: return qs class Country(models.Model, models.GeoMixin): name = models.CharField(maxlength=50) code = models.CharField(maxlength=2) point = models.PointField(null=True) objects = models.GeoManager() def __unicode__(self): return self.name class CountryBlock(models.Model): ipfrom = models.BigIntegerField(db_index=True) ipto = models.BigIntegerField(db_index=True) startip = models.IPAddressField() endip = models.IPAddressField() country = models.ForeignKey(Country) objects = IPManager() def __unicode__(self): return unicode('%s: %s to %s' % (self.country.name, self.startip, self.endip)) class Location(models.Model, models.GeoMixin): locid = models.IntegerField(db_index=True) country = models.ForeignKey(Country) region = models.CharField(maxlength=7, blank=True) city = models.CharField(maxlength=41, blank=True) postalcode = models.CharField(maxlength=7, blank=True) dmacode = models.CharField(maxlength=3, blank=True) areacode = models.CharField(maxlength=3, blank=True) point = models.PointField() objects = models.GeoManager() def __unicode__(self): return unicode('Location %d: %s - %s, %s %s' % (self.locid, self.country.name, self.region, self.city, self.postalcode)) class LocationBlock(models.Model): location = models.ForeignKey(Location) ipfrom = models.BigIntegerField(db_index=True) ipto = models.BigIntegerField(db_index=True) objects = IPManager()