pythondjangogeodjango

Geo Django get cities from latitude and longitude


I'm learning how to use Geo Django. When a user registers I save the latitude and longitude information as seen below:

from django.contrib.gis.db import models
from django.contrib.gis.geos import Point

class GeoModel(models.Model):
    """
    Abstract model to provide GEO fields.
    """
    latitude = models.FloatField(blank=True, null=True, verbose_name='Latitude')
    longitude = models.FloatField(blank=True, null=True, verbose_name='Longitude')
    location = models.PointField(blank=True, null=True)

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        if self.latitude and self.longitude:
            self.location = Point(float(self.latitude), float(self.longitude))
        super(GeoModel, self).save(*args, **kwargs)

Next I want to add a new field called city where **I want to store the city "name" i.e. London based the long and lat details given.

I have looked at django-cities where is saves a database of cities from Geo Name, but this seems overkill and not Python 3 compatible so a no go for me. I have seen a package called geopy but this seems to completely replace Geo Django and uses Google API which comes with restrictions.

I want to stick with Geo Django and somehow do a lookup to find out the City name based on long and lat so what are my options? i.e..

  1. Find a way to install http://www.geonames.org/ data django-cities does not work for Python 3 and Django 1.8.x
  2. Somehow use Geo Django to do this lookup using the data? (unsure ow to do this)

Is above the correct way to approach this? If so how do I get the data into my DB then do a lookup on it using Geo Django to find the city name?


Solution

  • You have several solutions to do this:

    1. Create another model City

      from django.contrib.gis.db import models
      class City(models.Model):
          name = models.CharField(max_lenght=255)
          geometry = models.MultiPolygonField()
      
          objects = models.GeoManager()
      

    Then you can find the name of the city containing your location with:

        geomodel = GeoModel(...)
        city = City.objects.get(geometry__contains=geomodel.location)
        city_name = city.name
    

    Depending on the country/region you are interested in, you may find city geometries to fill the City table in OpenData (eg http://www.gadm.org/country (not tested but seems to propose open shapefiles))

    1. Use an inverse geocoder. Google can provide such service or look at http://www.geonames.org/export/reverse-geocoding.html if something can match your needs.