import json import requests from django.contrib.gis.geos import GEOSGeometry, fromstr, MultiPolygon from django.contrib.gis.db import models from django.contrib.sitemaps import Sitemap from django.utils.safestring import mark_safe "http://staticmap.openstreetmap.de/staticmap.php?center=object.location.geometry.centroid.y,object.location.geometry.centroid.x&zoom=14&size=1140x300&maptype=osmarenderer&markers=40.702147,-74.015794,lightblue1" class Region(models.Model): """Model to define arbitrary regions based on where I've been""" name = models.CharField(max_length=50) slug = models.SlugField() pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPolygonField(srid=4326, null=True) lon = models.FloatField('Longitude', help_text="Longitude of centerpoint", null=True) lat = models.FloatField('Latitude', help_text="Latitude of centerpoint", null=True) zoom_level = models.CharField(max_length=2, null=True) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() def get_absolute_url(self): return "/locations/region/%s/" % (self.slug) def __str__(self): return self.name class Country(models.Model): """ A geographic model based on the v3 of the simplified world borders multipolygon shapefile from http://thematicmapping.org/downloads/world_borders.php. """ name = models.CharField(max_length=50) area = models.IntegerField(help_text="Area of Country in SQ meters") pop2005 = models.IntegerField('Population 2005') fips = models.CharField('FIPS Code', max_length=2, help_text=mark_safe('Federal Information Processing Standard Code')) iso2 = models.CharField('2 Digit ISO', max_length=2, help_text=mark_safe('International Organization for Standardization')) iso3 = models.CharField('3 Digit ISO', max_length=3, help_text=mark_safe('International Organization for Standardization')) un = models.IntegerField('United Nations Code') REGION_CODES = ( (0, 'MISC'), (2, 'Africa'), (9, 'Oceania'), (19, 'Americas'), (142, 'Asia'), (150, 'Europe'), ) SUBREGION_CODES = ( (0, 'MISC'), (5, 'South America'), (11, 'Western Africa'), (13, 'Central America'), (14, 'Eastern Africa'), (15, 'Northern Africa'), (17, 'Middle Africa'), (18, 'Southern Africa'), (21, 'North America'), (29, 'Caribbean'), (30, 'Eastern Asia'), (34, 'Southern Asia'), (35, 'Southeast Asia'), (39, 'Southern Europe'), (53, 'Australia and New Zealand'), (54, 'Melanesia'), (57, 'Micronesia'), (61, 'Polynesia'), (143, 'Central Asia'), (145, 'Western Asia'), (151, 'Eastern Europe'), (154, 'Northern Europe'), (155, 'Western Europe'), ) region = models.IntegerField('Region Code', choices=REGION_CODES) subregion = models.IntegerField('Sub-Region Code', choices=SUBREGION_CODES) lon = models.FloatField('Longitude', help_text="Longitude of centerpoint") lat = models.FloatField('Latitude', help_text="Latitude of centerpoint") zoom_level = models.CharField(max_length=2, null=True) slug = models.SlugField(null=True) visited = models.BooleanField(default=False) lux_region = models.ForeignKey(Region, null=True) pub_date = models.DateTimeField('Date published', null=True) geometry = models.MultiPolygonField('Country Border', srid=4326) objects = models.GeoManager() class Meta: ordering = ['name'] verbose_name_plural = 'Countries' def __str__(self): return self.name def get_absolute_url(self): return "/locations/%s/" % (self.slug) class State(models.Model): """Model to hold state boundaries""" name = models.CharField(max_length=250, blank=True, null=True,) country = models.ForeignKey(Country) slug = models.SlugField() code = models.CharField(max_length=2, null=True, blank=True) pub_date = models.DateTimeField('Date published', null=True) geometry = models.MultiPolygonField(srid=4326, null=True) objects = models.GeoManager() class Meta: ordering = ['name'] def __str__(self): return "%s" % (self.name) def get_absolute_url(self): return "/locations/%s/%s/" % (self.country.slug, self.slug) class Location(models.Model): """Model to hold location shapes as arbitrarily defined by me""" state = models.ForeignKey(State) name = models.CharField(max_length=50, ) slug = models.SlugField() pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPolygonField(srid=4326) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() def __str__(self): return self.name def comma_name(self): if self.state.country.name == "United States": return self.state else: return self.state.country def get_absolute_url(self): return "/locations/%s/%s/%s/" % (self.state.country.slug, self.state.slug, self.slug) class Route(models.Model): """Model to hold routes for longer trips""" name = models.CharField(max_length=200) slug = models.SlugField() zoom = models.CharField(max_length=2, null=True) template_var_name = models.CharField(max_length=10, null=True) pub_date = models.DateTimeField('Date published', null=True) # GeoDjango specific Polygon Field and GeoManager geometry = models.MultiPointField(srid=4326) # GeoManager, a subclass that adds a rich set of geospatial queryset methods objects = models.GeoManager() def get_absolute_url(self): return "/locations/%s/%s/%s/" % (self.slug) def __str__(self): return self.name class WritingbyCountrySitemap(Sitemap): changefreq = "weekly" priority = 0.6 protocol = "https" def location(self, item): return '/jrnl/%s' % item.slug def items(self): return Country.objects.filter(visited=True) def get_bounds(lat, lon): ''' given a set of lat,lon coords return the nearest administrative level boundary (usually turn out to be city, but sometimes it's a county, occasionally a state) ''' r = requests.get('http://nominatim.openstreetmap.org/reverse', params={ 'lat': lat, 'lon': lon, 'accept-language': 'en', 'format': 'json' }) r.raise_for_status() data = json.loads(r.text) adr = data.get('address', {}) city = adr.get('hamlet') or adr.get('village') or adr.get('town') or adr.get('city') state = adr.get('state') country = adr.get('country') r = requests.get('http://nominatim.openstreetmap.org/search', params={ 'city': city, 'state': state, 'country': country, 'polygon_text': 1, 'format': 'json', 'featuretype': 'neighborhood' }) r.raise_for_status() data = json.loads(r.text) poly = GEOSGeometry(data[0]['geotext']) # Sometimes you get a multipolygon, sometimes just a polygon if poly.geom_type == 'Polygon': poly = MultiPolygon(fromstr(data[0]['geotext'])) return poly