Django GeoIP — определение местоположения посетителя средствами Django Framework

На днях в одном из преоектов пришлось прикручивать функционал определения страны нахождения пользователя по IP адресу. По сути задача не сложная, если знать как это делается. Но основная проблема состояла в том, чтобы названия государств выводились на русском и/или английском языках. Постораюсь коротко, без лишней воды и болтовни, пошагово описать все действия по установке библиотек и настройке проекта.

Чтобы добавить в проект приложение Django GIS достаточно в INSTALLED_APPS вписать 'django.contrib.gis'. Так пишут здесь. Но они не предупреждают, что все весь проект после этого разваливается, если не установлены необходимые библиотеки и базы. В статье использованы материалы официальной документации и собственные разработки.


Начнем с установки всех необходимых библиотек и баз данных. Что нам нужно?

  • Python 2.4+
  • Django
  • PostgreSQL (с PostGIS), MySQL или Oracle (я использую PostgreSQL)
  • GEOS
  • PROJ.4


Единственная нерешенная проблема — это ошибка приподключенном 'haystack'. Поэтому пришлось временно удалить его из проекта.

Все устанавливаем с исходников

Установка 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 ..


Установка PROJ.4



Это библиотека, конвертирующая геопространственные данные в различных системах координат.

$ 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



PostGIS добавляет поддержку географического объекта PostgreSQL, превратив его в базу картографических данных. GEOS и PROJ.4 должны быть установлены до начала сборки 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 ..


Создание пространственного шаблон базы данных для PostGIS



$ sudo su - postgres


Дальше на странице документации качаем подходящий скрипт и запускаем. После этого вы можете создать пространственную базу данных, просто указав template_postgis как шаблон для использования (с помощью опции-T):

$ createdb -T template_postgis <db name>


Библиотеки установлены. Теперь качаем базы стран и городов. Распаковываем. Я для удобства файлы размещаю в директории MEDIA_ROOT/geoip

Вот теперь пора работать с settings.py проекта:

INSTALLED_APPS = (
    #....................
    'django.contrib.gis',
    #....................
)
#..............................................
GEOIP_PATH = os.path.join(MEDIA_ROOT, 'geoip')
GEOIP_COUNTRY = 'GeoIP.dat'
GEOIP_CITY = 'GeoLiteCity.dat'


Теперь можете тестировать. Код для тестирования я не буду копипастить. Смотрите здесь docs.djangoproject.com/en/1.3/ref/contrib/gis/geoip/#example. Да и документацию, думаю, не стоит переводить. Следующий вопрос, которому стоит уделить внимание, это русификация. Как получить название страны на русском языке?

Для этого я создал три модели:

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')


В интернете я нашел несколько красивых баз стран и городов, и скомпилировал в одну со всеми нужными мне полями. Ссылки на базы выкладывать не буду, стучите в личку.

А работает весь этот механизм следующим образом.

# Подключаем модуль
>>> 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


На этом всё. Возможно что то лишнее, но я постарался максимально сжато указать на основные моменты. Спасибо всем за внимание.

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 13

    +2
    А почему всё ставится из исходников? На сколько знаю, принято использовать virtualenv и pip. Тогда нет возни с исходниками.
      0
      Из исходников для наглядности, а pip install postgis не встречал. Неужели работает?
        0
        $ pip search PostGIS
        imposm — OpenStreetMap importer for PostGIS.
        django-postalcodes — Postal code management with geolocation (for GeoDjango and PostGIS)
        dbgis — PostGIS/SpatiaLite adapter for Psycopg/pyspatialite
        PPyGIS — PostGIS adapter for Psycopg
        django-geomodels — Geo models for Django and PostGIS wth geonames.org data import.

        то что надо?
          0
          И на сервере как понимаю Linux стоит...? Библиотеки может быть лучше через менеджер пакетов поставить, или их там нет просто?
            0
            Да. Ставил на Gentoo через emerge. Повторюсь: описываю установку из исходников, так как менеджеры пакетов везде разные. Зачем дублировать код для ubuntu, debian, fedor, etc.?
              0
              За тем, что бы потом не возникало конфликтов потом (и как оперативно проверить установлен тот или иной пакет?), менеджер пакетов занимается не просто установкой. А в своём дистрибутиве каждый знает как пользоваться менеджером пакетов и дублировать ничего не надо.
                0
                Я не спрашиваю зачем ставить через менеджер пакетов. Вчитавшись в ответ можно увидеть
                Ставил на Gentoo через emerge


                Вопрос был, зачем дублировать способ установки для каждого менеджера пакетов? Сам когда то только знакомился с linux и в gentoo при знакомстве с ним лично, и знать не знал, что RPM там не нужно использовать.

                На эту тему можно бесконечно спорить и каждый будет прав.
        0
        Объясните одну вещь: у maxmind'а есть библиотечки для работы с его бинарными базами (которые (базы), на минуточку, представляют собой просто два файла). Что же тогда делает все это: GEOS, PROJ.4, PostGIS (???), не считая контриб-модуля самой джанги?
          0
          Большая часть из перечисленного используется для жонглирования геоданными.
          На счет maxmindа: есть многое на свете — например, базы Sypex Geo + pysyge.
            0
            Бинарные базы есть. И они установлены. Об этом я писал еще в начале (один из первых шагов). Как же без них?
            И как сказал уважаемый idle: «Большая часть из перечисленного используется для жонглирования геоданными».
              0
              А вот библиотечки не нашел. Плохо искал? Да.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое