Содержание
На днях в одном из преоектов пришлось прикручивать функционал определения страны нахождения пользователя по 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
На этом всё. Возможно что то лишнее, но я постарался максимально сжато указать на основные моменты. Спасибо всем за внимание.