add GeometryField and features api endpoint
This commit is contained in:
parent
de35a20854
commit
e6cbe5bf27
8 changed files with 100 additions and 5 deletions
24
src/c3nav/api/fields.py
Normal file
24
src/c3nav/api/fields.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from rest_framework import serializers
|
||||||
|
from rest_framework.exceptions import ValidationError
|
||||||
|
from shapely.geometry import mapping, shape
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryField(serializers.DictField):
|
||||||
|
"""
|
||||||
|
shapely geometry objects serialized using GeoJSON
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _('Invalid GeoJSON.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_representation(self, obj):
|
||||||
|
geojson = mapping(obj)
|
||||||
|
return super().to_representation(geojson)
|
||||||
|
|
||||||
|
def to_internal_value(self, data):
|
||||||
|
geojson = super().to_internal_value(data)
|
||||||
|
try:
|
||||||
|
return shape(geojson)
|
||||||
|
except:
|
||||||
|
raise ValidationError(_('Invalid GeoJSON.'))
|
|
@ -2,7 +2,8 @@ from django.conf import settings
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from ..editor.hosters import get_hoster_for_package
|
from ..editor.hosters import get_hoster_for_package
|
||||||
from ..mapdata.models import Level, Package, Source
|
from ..mapdata.models import Feature, Level, Package, Source
|
||||||
|
from .fields import GeometryField
|
||||||
from .permissions import can_access_package
|
from .permissions import can_access_package
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +43,14 @@ class FeatureTypeSerializer(serializers.Serializer):
|
||||||
color = serializers.CharField()
|
color = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureSerializer(serializers.ModelSerializer):
|
||||||
|
geometry = GeometryField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Feature
|
||||||
|
fields = ('name', 'package', 'feature_type', 'geometry')
|
||||||
|
|
||||||
|
|
||||||
class HosterSerializer(serializers.Serializer):
|
class HosterSerializer(serializers.Serializer):
|
||||||
name = serializers.CharField()
|
name = serializers.CharField()
|
||||||
base_url = serializers.CharField()
|
base_url = serializers.CharField()
|
||||||
|
|
|
@ -9,6 +9,7 @@ router.register(r'levels', mapdata_views.LevelViewSet)
|
||||||
router.register(r'packages', mapdata_views.PackageViewSet)
|
router.register(r'packages', mapdata_views.PackageViewSet)
|
||||||
router.register(r'sources', mapdata_views.SourceViewSet)
|
router.register(r'sources', mapdata_views.SourceViewSet)
|
||||||
router.register(r'featuretypes', mapdata_views.FeatureTypeViewSet, base_name='featuretype')
|
router.register(r'featuretypes', mapdata_views.FeatureTypeViewSet, base_name='featuretype')
|
||||||
|
router.register(r'features', editor_views.FeatureViewSet)
|
||||||
router.register(r'hosters', editor_views.HosterViewSet, base_name='hoster')
|
router.register(r'hosters', editor_views.HosterViewSet, base_name='hoster')
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ViewSet
|
from rest_framework.viewsets import ModelViewSet, ViewSet
|
||||||
|
|
||||||
from ...editor.hosters import hosters
|
from ...editor.hosters import hosters
|
||||||
from ..serializers import HosterSerializer
|
from ...mapdata.models import Feature
|
||||||
|
from ..serializers import FeatureSerializer, HosterSerializer
|
||||||
|
|
||||||
|
|
||||||
class HosterViewSet(ViewSet):
|
class HosterViewSet(ViewSet):
|
||||||
|
@ -19,3 +20,12 @@ class HosterViewSet(ViewSet):
|
||||||
raise Http404
|
raise Http404
|
||||||
serializer = HosterSerializer(hosters[pk], context={'request': request})
|
serializer = HosterSerializer(hosters[pk], context={'request': request})
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureViewSet(ModelViewSet):
|
||||||
|
"""
|
||||||
|
Get all Map Features including ones that are only part of the current session
|
||||||
|
"""
|
||||||
|
queryset = Feature.objects.all()
|
||||||
|
serializer_class = FeatureSerializer
|
||||||
|
lookup_value_regex = '[^/]+'
|
||||||
|
|
17
src/c3nav/mapdata/fields.py
Normal file
17
src/c3nav/mapdata/fields.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from shapely.geometry import mapping, shape
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryField(models.TextField):
|
||||||
|
def from_db_value(self, value, expression, connection, context):
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
return shape(json.loads(value))
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
return shape(json.loads(value))
|
||||||
|
|
||||||
|
def get_prep_value(self, value):
|
||||||
|
return json.dumps(mapping(value))
|
31
src/c3nav/mapdata/migrations/0004_auto_20160920_1356.py
Normal file
31
src/c3nav/mapdata/migrations/0004_auto_20160920_1356.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.1 on 2016-09-20 13:56
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import c3nav.mapdata.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0003_package_commit_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='feature',
|
||||||
|
name='type',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='feature',
|
||||||
|
name='feature_type',
|
||||||
|
field=models.CharField(choices=[('building', 'Building'), ('room', 'Room'), ('outside', 'Outside Area'), ('obstacle', 'Obstacle')], default=None, max_length=50),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='feature',
|
||||||
|
name='geometry',
|
||||||
|
field=c3nav.mapdata.fields.GeometryField(),
|
||||||
|
),
|
||||||
|
]
|
|
@ -3,6 +3,8 @@ from collections import OrderedDict, namedtuple
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from ..fields import GeometryField
|
||||||
|
|
||||||
|
|
||||||
class FeatureType(namedtuple('FeatureType', ('name', 'title', 'title_plural', 'geomtype', 'color'))):
|
class FeatureType(namedtuple('FeatureType', ('name', 'title', 'title_plural', 'geomtype', 'color'))):
|
||||||
def __init__(self, *args, **kwartgs):
|
def __init__(self, *args, **kwartgs):
|
||||||
|
@ -27,8 +29,8 @@ class Feature(models.Model):
|
||||||
name = models.SlugField(_('feature identifier'), primary_key=True, max_length=50, help_text=_('e.g. noc'))
|
name = models.SlugField(_('feature identifier'), primary_key=True, max_length=50, help_text=_('e.g. noc'))
|
||||||
package = models.ForeignKey('Package', on_delete=models.CASCADE, related_name='features',
|
package = models.ForeignKey('Package', on_delete=models.CASCADE, related_name='features',
|
||||||
verbose_name=_('map package'))
|
verbose_name=_('map package'))
|
||||||
type = models.CharField(max_length=50, choices=TYPES)
|
feature_type = models.CharField(max_length=50, choices=TYPES)
|
||||||
geometry = models.TextField()
|
geometry = GeometryField()
|
||||||
|
|
||||||
|
|
||||||
class FeatureTitle(models.Model):
|
class FeatureTitle(models.Model):
|
||||||
|
|
|
@ -4,3 +4,4 @@ django-compressor==2.1
|
||||||
csscompressor
|
csscompressor
|
||||||
djangorestframework>=3.4,<3.5
|
djangorestframework>=3.4,<3.5
|
||||||
django-filter>=0.14,<0.15
|
django-filter>=0.14,<0.15
|
||||||
|
shapely>=1.5,<1.6
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue