diff --git a/bikemap/settings.py b/bikemap/settings.py index bf97271..7a83ba7 100644 --- a/bikemap/settings.py +++ b/bikemap/settings.py @@ -37,6 +37,7 @@ INSTALLED_APPS = ( 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.gis', 'django_extensions', 'home', 'tracking', @@ -80,8 +81,9 @@ WSGI_APPLICATION = 'bikemap.wsgi.application' DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'NAME': 'bikemap_gis', + 'USER': 'tsouza' } } diff --git a/tracking/data/Readme.txt b/tracking/data/Readme.txt new file mode 100644 index 0000000..e77c8d0 --- /dev/null +++ b/tracking/data/Readme.txt @@ -0,0 +1,70 @@ +TM_WORLD_BORDERS-0.1.ZIP + +Provided by Bjorn Sandvik, thematicmapping.org + +Use this dataset with care, as several of the borders are disputed. + +The original shapefile (world_borders.zip, 3.2 MB) was downloaded from the Mapping Hacks website: +http://www.mappinghacks.com/data/ + +The dataset was derived by Schuyler Erle from public domain sources. +Sean Gilles did some clean up and made some enhancements. + + +COLUMN TYPE DESCRIPTION + +Shape Polygon Country/area border as polygon(s) +FIPS String(2) FIPS 10-4 Country Code +ISO2 String(2) ISO 3166-1 Alpha-2 Country Code +ISO3 String(3) ISO 3166-1 Alpha-3 Country Code +UN Short Integer(3) ISO 3166-1 Numeric-3 Country Code +NAME String(50) Name of country/area +AREA Long Integer(7) Land area, FAO Statistics (2002) +POP2005 Double(10,0) Population, World Polulation Prospects (2005) +REGION Short Integer(3) Macro geographical (continental region), UN Statistics +SUBREGION Short Integer(3) Geogrpahical sub-region, UN Statistics +LON FLOAT (7,3) Longitude +LAT FLOAT (6,3) Latitude + + +CHANGELOG VERSION 0.3 - 30 July 2008 + +- Corrected spelling mistake (United Arab Emirates) +- Corrected population number for Japan +- Adjusted long/lat values for India, Italy and United Kingdom + + +CHANGELOG VERSION 0.2 - 1 April 2008 + +- Made new ZIP archieves. No change in dataset. + + +CHANGELOG VERSION 0.1 - 13 March 2008 + +- Polygons representing each country were merged into one feature +- Åland Islands was extracted from Finland +- Hong Kong was extracted from China +- Holy See (Vatican City) was added +- Gaza Strip and West Bank was merged into "Occupied Palestinean Territory" +- Saint-Barthelemy was extracted from Netherlands Antilles +- Saint-Martin (Frensh part) was extracted from Guadeloupe +- Svalbard and Jan Mayen was merged into "Svalbard and Jan Mayen Islands" +- Timor-Leste was extracted from Indonesia +- Juan De Nova Island was merged with "French Southern & Antarctic Land" +- Baker Island, Howland Island, Jarvis Island, Johnston Atoll, Midway Islands + and Wake Island was merged into "United States Minor Outlying Islands" +- Glorioso Islands, Parcel Islands, Spartly Islands was removed + (almost uninhabited and missing ISO-3611-1 code) + +- Added ISO-3166-1 codes (alpha-2, alpha-3, numeric-3). Source: + https://www.cia.gov/library/publications/the-world-factbook/appendix/appendix-d.html + http://unstats.un.org/unsd/methods/m49/m49alpha.htm + http://www.fysh.org/~katie/development/geography.txt +- AREA column has been replaced with data from UNdata: + Land area, 1000 hectares, 2002, FAO Statistics +- POPULATION column (POP2005) has been replaced with data from UNdata: + Population, 2005, Medium variant, World Population Prospects: The 2006 Revision +- Added region and sub-region codes from UN Statistics Division. Source: + http://unstats.un.org/unsd/methods/m49/m49regin.htm +- Added LAT, LONG values for each country + diff --git a/tracking/data/TM_WORLD_BORDERS-0.3.dbf b/tracking/data/TM_WORLD_BORDERS-0.3.dbf new file mode 100644 index 0000000..64ea895 Binary files /dev/null and b/tracking/data/TM_WORLD_BORDERS-0.3.dbf differ diff --git a/tracking/data/TM_WORLD_BORDERS-0.3.prj b/tracking/data/TM_WORLD_BORDERS-0.3.prj new file mode 100644 index 0000000..f45cbad --- /dev/null +++ b/tracking/data/TM_WORLD_BORDERS-0.3.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] \ No newline at end of file diff --git a/tracking/data/TM_WORLD_BORDERS-0.3.shp b/tracking/data/TM_WORLD_BORDERS-0.3.shp new file mode 100644 index 0000000..7cd47e9 Binary files /dev/null and b/tracking/data/TM_WORLD_BORDERS-0.3.shp differ diff --git a/tracking/data/TM_WORLD_BORDERS-0.3.shx b/tracking/data/TM_WORLD_BORDERS-0.3.shx new file mode 100644 index 0000000..dee32c2 Binary files /dev/null and b/tracking/data/TM_WORLD_BORDERS-0.3.shx differ diff --git a/tracking/data/TM_WORLD_BORDERS-0.3.zip b/tracking/data/TM_WORLD_BORDERS-0.3.zip new file mode 100644 index 0000000..92d14d4 Binary files /dev/null and b/tracking/data/TM_WORLD_BORDERS-0.3.zip differ diff --git a/tracking/management/commands/import_gpx.py b/tracking/management/commands/import_gpx.py index 86f2c2b..9e161ed 100644 --- a/tracking/management/commands/import_gpx.py +++ b/tracking/management/commands/import_gpx.py @@ -2,6 +2,7 @@ __author__ = 'tyrel' from django.core.management.base import BaseCommand, CommandError from django.contrib.auth.models import User from tracking.models import Track, Segment, Point +from django.contrib.gis import geos import xmltodict import os @@ -23,56 +24,43 @@ class Command(BaseCommand): except User.DoesNotExist: raise CommandError("User {0} does not exist".format(self.username)) - if os.path.isdir(filepath): - self.import_directory(filepath) - elif os.path.isfile(filepath): + if os.path.isfile(filepath): self.import_file(filepath) - else: raise CommandError("{0} is neither an existing file, nor a path.".format(filepath)) - def import_directory(self, directory): - pass - def import_file(self, filename): with open(filename) as fd: obj = dict(xmltodict.parse(fd.read()))['gpx'] + user = self.user - metadata = obj['metadata'] - tracks = obj['trk'] - - start_time = metadata['time'] - - name = tracks['name'] - segments = tracks['trkseg'] - if isinstance(segments, list): - raise NotImplemented( - "Haven't run across one that has multiple segments. " - "Contribute a patch if you have.") - elif isinstance(segments, dict): - # TODO: IF multiple import! - track = Track.objects.create(user=self.user, - start=start_time, - name=name) - points = segments['trkpt'] - segment = Segment(track=track, time=points[0]['time']) - segment.save() - print len(points) - for pt in points: - Point.objects.create(segment=segment, - time=pt['time'], - elevation=pt['ele'], - latitude=pt['@lat'], - longitude=pt['@lon']) - print "created Track <{0}> start: {1}, stop: {2}".format( - track.name, - track.start, - track.finish - ) + create_points_segments_tracks(obj, user) -def etree_to_dict(t): - d = {t.tag: map(etree_to_dict, t.getchildren())} - d.update(('@' + k, v) for k, v in t.attrib.iteritems()) - d['text'] = t.text - return d +def create_points_segments_tracks(obj, user): + # Get some Meta data from the gpx file. + metadata = obj['metadata'] + start_time = metadata['time'] + # Get the the track and segments from the gpx file. + tracks = obj['trk'] + name = tracks['name'] + segments = tracks['trkseg'] + # Check unimplemented features + if isinstance(segments, list): + raise NotImplemented( + "Haven't run across one that has multiple segments. " + "Contribute a patch if you have.") + elif isinstance(segments, dict): + track = Track.objects.create(user=user, + start=start_time, + name=name) + points = segments['trkpt'] + segment = Segment(track=track, time=points[0]['time']) + segment.save() + for pt in points: + lat, lon = float(pt['@lat']), float(pt['@lon']) + poly_pt = geos.Point(lon, lat) + Point.objects.create(segment=segment, + time=pt['time'], + elevation=pt['ele'], + point=poly_pt) diff --git a/tracking/migrations/0001_initial.py b/tracking/migrations/0001_initial.py index 3852cf7..7c21245 100644 --- a/tracking/migrations/0001_initial.py +++ b/tracking/migrations/0001_initial.py @@ -2,11 +2,14 @@ from __future__ import unicode_literals from django.db import models, migrations +from django.conf import settings +import django.contrib.gis.db.models.fields class Migration(migrations.Migration): dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ @@ -15,15 +18,16 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('time', models.DateTimeField()), - ('latitude', models.FloatField()), - ('longitude', models.FloatField()), ('elevation', models.DecimalField(max_digits=20, decimal_places=2)), + ('point', django.contrib.gis.db.models.fields.PointField(srid=4326)), ], ), migrations.CreateModel( name='Segment', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('time', models.DateTimeField()), + ('number', models.IntegerField(default=1)), ], ), migrations.CreateModel( @@ -33,6 +37,7 @@ class Migration(migrations.Migration): ('start', models.DateTimeField()), ('name', models.CharField(max_length=1024)), ('description', models.TextField(blank=True)), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), ], ), migrations.AddField( diff --git a/tracking/migrations/0002_auto_20150901_0355.py b/tracking/migrations/0002_auto_20150901_0355.py deleted file mode 100644 index eacda5b..0000000 --- a/tracking/migrations/0002_auto_20150901_0355.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tracking', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='point', - name='latitude', - field=models.DecimalField(max_digits=13, decimal_places=10), - ), - migrations.AlterField( - model_name='point', - name='longitude', - field=models.DecimalField(max_digits=12, decimal_places=10), - ), - ] diff --git a/tracking/migrations/0003_track_user.py b/tracking/migrations/0003_track_user.py deleted file mode 100644 index b5b9608..0000000 --- a/tracking/migrations/0003_track_user.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -from django.conf import settings - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('tracking', '0002_auto_20150901_0355'), - ] - - operations = [ - migrations.AddField( - model_name='track', - name='user', - field=models.ForeignKey(default=None, to=settings.AUTH_USER_MODEL), - preserve_default=False, - ), - ] diff --git a/tracking/migrations/0004_segment_number.py b/tracking/migrations/0004_segment_number.py deleted file mode 100644 index eb221d6..0000000 --- a/tracking/migrations/0004_segment_number.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tracking', '0003_track_user'), - ] - - operations = [ - migrations.AddField( - model_name='segment', - name='number', - field=models.IntegerField(default=1), - ), - ] diff --git a/tracking/migrations/0005_segment_time.py b/tracking/migrations/0005_segment_time.py deleted file mode 100644 index 8984e35..0000000 --- a/tracking/migrations/0005_segment_time.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -import datetime - - -class Migration(migrations.Migration): - - dependencies = [ - ('tracking', '0004_segment_number'), - ] - - operations = [ - migrations.AddField( - model_name='segment', - name='time', - field=models.DateTimeField(default=datetime.datetime(2015, 9, 1, 0, 43, 4, 754000)), - preserve_default=False, - ), - ] diff --git a/tracking/migrations/0006_auto_20150901_0054.py b/tracking/migrations/0006_auto_20150901_0054.py deleted file mode 100644 index 594b26a..0000000 --- a/tracking/migrations/0006_auto_20150901_0054.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tracking', '0005_segment_time'), - ] - - operations = [ - migrations.AlterField( - model_name='point', - name='latitude', - field=models.DecimalField(max_digits=10, decimal_places=6), - ), - migrations.AlterField( - model_name='point', - name='longitude', - field=models.DecimalField(max_digits=10, decimal_places=6), - ), - ] diff --git a/tracking/models.py b/tracking/models.py index 6de8133..2a6faeb 100644 --- a/tracking/models.py +++ b/tracking/models.py @@ -1,4 +1,5 @@ -from django.db import models +from django.contrib.gis.db import models + # Create your models here. from django.contrib.auth.models import User @@ -39,15 +40,18 @@ class Segment(models.Model): class Point(models.Model): time = models.DateTimeField() - latitude = models.DecimalField(max_digits=10, decimal_places=6) - longitude = models.DecimalField(max_digits=10, decimal_places=6) elevation = models.DecimalField(max_digits=20, decimal_places=2) segment = models.ForeignKey(Segment) + # GeoDjango-specific: a geometry field (MultiPolygonField), and + # overriding the default manager with a GeoManager instance. + point = models.PointField() + objects = models.GeoManager() + def __str__(self): return "'{name}' ({lat},{lon}) -> {alt} on {time}".format( - lat=self.latitude, - lon=self.longitude, + lat=self.point.x, + lon=self.point.y, alt=self.elevation, time=self.time, name=self.segment.track.name)