diff --git a/README.md b/README.md index be3cea5..6d96b53 100644 --- a/README.md +++ b/README.md @@ -18,18 +18,30 @@ several operations for querying data inside JSONB fields. See: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/fields/#containment-and-key-operations -## Usage - - python manage.py transformap -i jobs/jobfile.json - -Admin interface: /admin -API URL: /places-api/ -New jobs should be created as .YAML files in jobs/ - ## Misc ETL business logic: places/management/commands REST API configuration: places/api.py +## Deployment + +For development, testing or demo purposes, use the Django development server: + +python manage.py runserver 0.0.0.0:9000 + +Navigate to http://localhost:9000 ... + +- /admin for the Admin area +- /places-api for the REST API interface +- /map-instance/MAP-INSTANCE-ID for the GEOJSON API + +For production use, deploy Django using WSGI. See: +https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/ + +## Usage + +To run a job, create a YAML job file in /jobs, then: + python manage.py transformap -i jobs/jobfile.yaml +This fetch and save the partner's data to the database. \ No newline at end of file diff --git a/places/api.py b/places/api.py index 03382bd..a6efdf2 100644 --- a/places/api.py +++ b/places/api.py @@ -15,17 +15,34 @@ class MapOwnerViewSet(viewsets.ModelViewSet): queryset = MapOwner.objects.all() serializer_class = MapOwnerSerializer -# Map Instance -class MapInstanceSerializer(serializers.HyperlinkedModelSerializer): + +# Map Data + +class MapDataSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = MapData + fields = ('map_instance', 'map_object', 'schema_field', 'field_value', 'date_created', 'date_modified') + +class MapDataViewSet(viewsets.ModelViewSet): + queryset = MapData.objects.all() + serializer_class = MapDataSerializer + + + +# Map Instance (lite) + +class MapInstanceSerializer(serializers.ModelSerializer): + class Meta: model = MapInstance - fields = ('schema', 'map_definition', 'date_created', 'date_modified') + fields = ('id', 'schema', 'map_definition', 'date_created', 'date_modified',) class MapInstanceViewSet(viewsets.ModelViewSet): queryset = MapInstance.objects.all() serializer_class = MapInstanceSerializer - + + # Map Object class MapObjectSerializer(serializers.HyperlinkedModelSerializer): @@ -36,17 +53,6 @@ class Meta: class MapObjectViewSet(viewsets.ModelViewSet): queryset = MapObject.objects.all() serializer_class = MapObjectSerializer - -# Map Data - -class MapDataSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = MapData - fields = ('map_instance', 'map_object', 'schema_field', 'field_value', 'date_created', 'date_modified') - -class MapDataViewSet(viewsets.ModelViewSet): - queryset = MapData.objects.all() - serializer_class = MapDataSerializer # Map Definition diff --git a/places/models.py b/places/models.py index a1ef4c2..95ffea1 100644 --- a/places/models.py +++ b/places/models.py @@ -49,7 +49,7 @@ class MapInstance(models.Model): date_modified = models.DateTimeField(auto_now=True) def __unicode__(self): - return u'%s' % self.map_definition + return u'%s %s' % (self.map_definition, self.id) class Meta: db_table = 'map_instances' diff --git a/places/views.py b/places/views.py index 91ea44a..ac45130 100644 --- a/places/views.py +++ b/places/views.py @@ -1,3 +1,80 @@ +from urlparse import urlparse + from django.shortcuts import render +from django.http import HttpResponse, JsonResponse +from django.core.exceptions import ObjectDoesNotExist + +from places.models import MapInstance, MapData, MapObject # Create your views here. + +def map_instance_geojson(request, map_instance_id): + + ''' + Fetched all objects (and properties) for a given map instance, + returns a GEOJSON feature collection. + ''' + + # Fetch the map instance + + try: + map_instance = MapInstance.objects.get(id=map_instance_id) + except ObjectDoesNotExist: + return JsonResponse({"Error" : "Map Instance with ID %s does not exist!" % map_instance_id}) + + # Deduce URL from request + + request_url = urlparse(request.build_absolute_uri()) + base_url = 'http://%s%s' % (request_url.netloc, request_url.path) + + # Set pagination params + + page = int(request.GET.get('page', 1)) + x = (page - 1) * 25 + y = page * 25 + + # Prepare GEOJSON response + + response = { + "type" : "Feature Collection", + "count" : 25, + "next" : "%s?page=%s" % (base_url, page + 1), + } + + if page <= 1: + response['previous'] = None + else: + response['previous'] = "%s?page=%s" % (base_url, page - 1) + + # Fetch and serialise map objects + + map_objects = MapObject.objects.filter(map_instance=map_instance).order_by('id')[x:y] + + features = [] + for map_object in map_objects: + feature = { + "type" : "Feature", + "geometry" : { + "type" : "Point", + "coordinates": [ + float(map_object.longitude), + float(map_object.latitude), + ] + }, + "properties" : {} + } + + object_data = MapData.objects.filter(map_object=map_object) + + for field in object_data: + field_name = field.schema_field + feature["properties"][field.schema_field.field_name] = field.field_value + + features.append(feature) + + response['features'] = features + + return JsonResponse(response, safe=False) + + + \ No newline at end of file diff --git a/tfm/urls.py b/tfm/urls.py index 8a8ce27..77d0fb6 100644 --- a/tfm/urls.py +++ b/tfm/urls.py @@ -1,10 +1,11 @@ from django.conf.urls import url, include from django.contrib import admin -import places.api +import places.api, places.views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^places-api/', include(places.api.router.urls)), + url(r'^map-instance/(?P\d+)/$', places.views.map_instance_geojson) ]