Django GeoIP - determining the location of a visitor using the Django Framework
- From the sandbox
- Tutorial
The other day, in one of the projects, I had to fasten the functionality of determining the country of the user's location by IP address. In fact, the task is not difficult if you know how to do it. But the main problem was that the names of states should be displayed in Russian and / or English. I will try briefly, without unnecessary water and chatter, step by step to describe all the steps for installing libraries and setting up a project.
To add a Django GIS application to the project, just enter 'django.contrib.gis' in INSTALLED_APPS. So write here . But they do not warn that the whole project after that falls apart if the necessary libraries and databases are not installed. The article used materials of official documentation and its own development.
Let's start by installing all the necessary libraries and databases. What we need?
The only unresolved issue is the error with the 'haystack' connected. Therefore, I had to temporarily remove it from the project.
We install everything from source
This is a library that converts geospatial data in various coordinate systems.
PostGIS adds support for the PostgreSQL geographic feature, turning it into a map database. GEOS and PROJ.4 must be installed before building PostGIS.
Further on the documentation page, download the appropriate script and run it. After that, you can create a spatial database by simply specifying template_postgis as the template to use (using the -T option):
Libraries are installed. Now download the base of countries and cities . Unpack. For convenience, I place the files in the directory MEDIA_ROOT / geoip
Now it’s time to work with the settings.py of the project:
Now you can test. I will not copy-paste the code for testing. See here docs.djangoproject.com/en/1.3/ref/contrib/gis/geoip/#example . Yes, and the documentation, I think, is not worth translating. The next question to which attention should be paid is Russification. How to get the name of the country in Russian?
For this, I created three models:
On the Internet, I found several beautiful databases of countries and cities, and compiled it into one with all the fields I need. I will not post links to the bases, knock on the PM.
And this whole mechanism works as follows.
That's all. Perhaps something superfluous, but I tried to indicate the main points as concisely as possible. Thank you all for your attention.
To add a Django GIS application to the project, just enter 'django.contrib.gis' in INSTALLED_APPS. So write here . But they do not warn that the whole project after that falls apart if the necessary libraries and databases are not installed. The article used materials of official documentation and its own development.
Let's start by installing all the necessary libraries and databases. What we need?
- Python 2.4+
- Django
- PostgreSQL (with PostGIS), MySQL or Oracle (I use PostgreSQL)
- Geos
- PROJ.4
The only unresolved issue is the error with the 'haystack' connected. Therefore, I had to temporarily remove it from the project.
We install everything from source
Install GEOS
$ wget http://download.osgeo.org/geos/geos-3.2.2.tar.bz2
$ tar xjf geos-3.2.2.tar.bz2
$ cd geos-3.2.2
$ ./configure
$ make
$ sudo make install
$ cd ..
Installation PROJ.4
This is a library that converts geospatial data in various coordinate systems.
$ wget http://download.osgeo.org/proj/proj-4.7.0.tar.gz
$ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.zip
$ tar xzf proj-4.7.0.tar.gz
$ cd proj-4.7.0/nad
$ unzip ../../proj-datumgrid-1.5.zip
$ cd ..
$ ./configure
$ make
$ sudo make install
$ cd ..
PostGIS Installation
PostGIS adds support for the PostgreSQL geographic feature, turning it into a map database. GEOS and PROJ.4 must be installed before building PostGIS.
$ wget http://postgis.refractions.net/download/postgis-1.5.2.tar.gz
$ tar xzf postgis-1.5.2.tar.gz
$ cd postgis-1.5.2
$ ./configure
$ make
$ sudo make install
$ cd ..
Creating a spatial database template for PostGIS
$ sudo su - postgres
Further on the documentation page, download the appropriate script and run it. After that, you can create a spatial database by simply specifying template_postgis as the template to use (using the -T option):
$ createdb -T template_postgis
Libraries are installed. Now download the base of countries and cities . Unpack. For convenience, I place the files in the directory MEDIA_ROOT / geoip
Now it’s time to work with the settings.py of the project:
INSTALLED_APPS = (
#....................
'django.contrib.gis',
#....................
)
#..............................................
GEOIP_PATH = os.path.join(MEDIA_ROOT, 'geoip')
GEOIP_COUNTRY = 'GeoIP.dat'
GEOIP_CITY = 'GeoLiteCity.dat'
Now you can test. I will not copy-paste the code for testing. See here docs.djangoproject.com/en/1.3/ref/contrib/gis/geoip/#example . Yes, and the documentation, I think, is not worth translating. The next question to which attention should be paid is Russification. How to get the name of the country in Russian?
For this, I created three models:
class WorldPart(models.Model):
name_ru = models.CharField(max_length=255, verbose_name=_('Name RU'), null=True, blank=True)
name_en = models.CharField(max_length=255, verbose_name=_('Name EN'), null=True, blank=True)
def __unicode__(self):
return self.name_ru
class Meta:
ordering = ['name_ru', 'name_en',]
verbose_name = _('Part of the World')
verbose_name_plural = _('Parts of the World')
class Country(models.Model):
name_ru = models.CharField(max_length=255, verbose_name=_('Name RU'), null=True, blank=True)
name_en = models.CharField(max_length=255, verbose_name=_('Name EN'), null=True, blank=True)
code = models.CharField(max_length=2, verbose_name=_('Code'), null=True, blank=True)
worldpart = models.ForeignKey(WorldPart, verbose_name=_('Part of the World'), null=True, blank=True)
flag = models.ImageField(upload_to=os.path.join(settings.STATIC_ROOT, 'img', 'flags'), verbose_name=_('Flag'), null=True, blank=True)
is_active = models.BooleanField(verbose_name=_('Is active'))
def __unicode__(self):
return self.name_ru
class Meta:
ordering = ['name_ru', 'name_en',]
verbose_name = _('Country')
verbose_name_plural = _('Countries')
class City(models.Model):
country = models.ForeignKey(Country, verbose_name=_('Country'))
name_ru = models.CharField(max_length=255, verbose_name=_('Name RU'), null=True, blank=True)
name_en = models.CharField(max_length=255, verbose_name=_('Name EN'), null=True, blank=True)
region = models.CharField(max_length=100, verbose_name=_('Region'), null=True, blank=True)
postal_code = models.CharField(max_length=10, verbose_name=_('Postal Code'), null=True, blank=True)
latitude = models.CharField(max_length=255, verbose_name=_('Lattitude'), null=True, blank=True)
longitude = models.CharField(max_length=255, verbose_name=_('Longitude'), null=True, blank=True)
is_active = models.BooleanField(verbose_name=_('Is active'))
def __unicode__(self):
return self.name_ru
class Meta:
ordering = ['name_ru', 'name_en',]
verbose_name = _('City')
verbose_name_plural = _('Cities')
On the Internet, I found several beautiful databases of countries and cities, and compiled it into one with all the fields I need. I will not post links to the bases, knock on the PM.
And this whole mechanism works as follows.
# Подключаем модуль
>>> from django.contrib.gis.utils import GeoIP
>>> from myapp.models import *
>>> g = GeoIP()
Получаем название государства
>>> cn = g.country('google.com')
>>> cn
{'country_code': 'US', 'country_name': 'United States'}
>>> try:
>>> cn_db = Country.objects.get(code=cn['country_code'])
>>> except Country.DoesNotExist:
>>> pass
That's all. Perhaps something superfluous, but I tried to indicate the main points as concisely as possible. Thank you all for your attention.