refactor api views inter their respecting apps
This commit is contained in:
parent
b69dff708e
commit
02cafee6be
12 changed files with 112 additions and 117 deletions
|
@ -1,26 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||
from ..mapdata.utils import sort_geojson
|
|
||||||
|
|
||||||
|
|
||||||
class GeometryField(serializers.DictField):
|
|
||||||
"""
|
|
||||||
shapely geometry objects serialized using GeoJSON
|
|
||||||
"""
|
|
||||||
default_error_messages = {
|
|
||||||
'invalid': _('Invalid GeoJSON.')
|
|
||||||
}
|
|
||||||
|
|
||||||
def to_representation(self, obj):
|
|
||||||
geojson = sort_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.'))
|
|
|
@ -1,63 +0,0 @@
|
||||||
from django.conf import settings
|
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from ..editor.hosters import get_hoster_for_package
|
|
||||||
from ..mapdata.models import Feature, Level, Package, Source
|
|
||||||
from .fields import GeometryField
|
|
||||||
from .permissions import can_access_package
|
|
||||||
|
|
||||||
|
|
||||||
class LevelSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Level
|
|
||||||
fields = ('name', 'altitude', 'package')
|
|
||||||
|
|
||||||
|
|
||||||
class PackageSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Package
|
|
||||||
fields = ('name', 'home_repo', 'commit_id', 'depends', 'bounds')
|
|
||||||
|
|
||||||
def to_representation(self, obj):
|
|
||||||
result = super().to_representation(obj)
|
|
||||||
result['public'] = obj.name in settings.PUBLIC_PACKAGES
|
|
||||||
hoster = get_hoster_for_package(obj)
|
|
||||||
if 'request' in self.context:
|
|
||||||
result['access_granted'] = can_access_package(self.context['request'], obj)
|
|
||||||
if hoster is not None:
|
|
||||||
result['hoster'] = hoster.name
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class SourceSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Source
|
|
||||||
fields = ('name', 'package', 'bounds')
|
|
||||||
|
|
||||||
|
|
||||||
class FeatureTypeSerializer(serializers.Serializer):
|
|
||||||
name = serializers.CharField()
|
|
||||||
title = serializers.CharField()
|
|
||||||
title_plural = serializers.CharField()
|
|
||||||
geomtype = 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):
|
|
||||||
name = serializers.CharField()
|
|
||||||
base_url = serializers.CharField()
|
|
||||||
|
|
||||||
def to_representation(self, obj):
|
|
||||||
result = super().to_representation(obj)
|
|
||||||
result['packages'] = tuple(obj.get_packages().values_list('name', flat=True))
|
|
||||||
if 'request' in self.context:
|
|
||||||
result['signed_in'] = obj.is_access_granted(self.context['request'])
|
|
||||||
return result
|
|
|
@ -1,16 +1,16 @@
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
from .views import editor as editor_views
|
from ..editor import api as editor_api
|
||||||
from .views import mapdata as mapdata_views
|
from ..mapdata import api as mapdata_api
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register(r'levels', mapdata_views.LevelViewSet)
|
router.register(r'levels', mapdata_api.LevelViewSet)
|
||||||
router.register(r'packages', mapdata_views.PackageViewSet)
|
router.register(r'packages', mapdata_api.PackageViewSet)
|
||||||
router.register(r'sources', mapdata_views.SourceViewSet)
|
router.register(r'sources', mapdata_api.SourceViewSet)
|
||||||
router.register(r'featuretypes', mapdata_views.FeatureTypeViewSet, base_name='featuretype')
|
router.register(r'featuretypes', mapdata_api.FeatureTypeViewSet, base_name='featuretype')
|
||||||
router.register(r'features', editor_views.FeatureViewSet)
|
router.register(r'features', mapdata_api.FeatureViewSet)
|
||||||
router.register(r'hosters', editor_views.HosterViewSet, base_name='hoster')
|
router.register(r'hosters', editor_api.HosterViewSet, base_name='hoster')
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
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 ModelViewSet, ViewSet
|
from rest_framework.viewsets import ViewSet
|
||||||
|
|
||||||
from ...editor.hosters import hosters
|
from .hosters import hosters
|
||||||
from ...mapdata.models import Feature
|
from .serializers import HosterSerializer
|
||||||
from ..serializers import FeatureSerializer, HosterSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class HosterViewSet(ViewSet):
|
class HosterViewSet(ViewSet):
|
||||||
|
@ -20,12 +19,3 @@ 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 = '[^/]+'
|
|
14
src/c3nav/editor/serializers.py
Normal file
14
src/c3nav/editor/serializers.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class HosterSerializer(serializers.Serializer):
|
||||||
|
name = serializers.CharField()
|
||||||
|
base_url = serializers.CharField()
|
||||||
|
packages = serializers.SerializerMethodField()
|
||||||
|
signed_in = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_packages(self, obj):
|
||||||
|
return tuple(obj.get_packages().values_list('name', flat=True))
|
||||||
|
|
||||||
|
def get_signed_in(self, obj):
|
||||||
|
return obj.is_access_granted(self.context['request']) if 'request' in self.context else None
|
|
@ -6,12 +6,12 @@ from django.core.files import File
|
||||||
from django.http import Http404, HttpResponse
|
from django.http import Http404, HttpResponse
|
||||||
from rest_framework.decorators import detail_route
|
from rest_framework.decorators import detail_route
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet, ViewSet
|
||||||
|
|
||||||
from ...mapdata.models import FEATURE_TYPES, Level, Package, Source
|
|
||||||
from ..permissions import filter_source_queryset
|
|
||||||
from ..serializers import FeatureTypeSerializer, LevelSerializer, PackageSerializer, SourceSerializer
|
|
||||||
from .cache import AccessCachedViewSetMixin, CachedViewSetMixin
|
from .cache import AccessCachedViewSetMixin, CachedViewSetMixin
|
||||||
|
from .models import FEATURE_TYPES, Feature, Level, Package, Source
|
||||||
|
from .permissions import filter_source_queryset
|
||||||
|
from .serializers import FeatureSerializer, FeatureTypeSerializer, LevelSerializer, PackageSerializer, SourceSerializer
|
||||||
|
|
||||||
|
|
||||||
class LevelViewSet(CachedViewSetMixin, ReadOnlyModelViewSet):
|
class LevelViewSet(CachedViewSetMixin, ReadOnlyModelViewSet):
|
||||||
|
@ -79,3 +79,15 @@ class FeatureTypeViewSet(ViewSet):
|
||||||
raise Http404
|
raise Http404
|
||||||
serializer = FeatureTypeSerializer(FEATURE_TYPES[pk], context={'request': request})
|
serializer = FeatureTypeSerializer(FEATURE_TYPES[pk], context={'request': request})
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
|
ParentModelViewSet = ModelViewSet if settings.DIRECT_EDITING else ReadOnlyModelViewSet
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureViewSet(ParentModelViewSet):
|
||||||
|
"""
|
||||||
|
Get all Map Features including ones that are only part of the current session
|
||||||
|
"""
|
||||||
|
queryset = Feature.objects.all()
|
||||||
|
serializer_class = FeatureSerializer
|
||||||
|
lookup_value_regex = '[^/]+'
|
|
@ -4,7 +4,7 @@ from django.core.cache import cache
|
||||||
from django.template.response import SimpleTemplateResponse
|
from django.template.response import SimpleTemplateResponse
|
||||||
from django.utils.cache import patch_vary_headers
|
from django.utils.cache import patch_vary_headers
|
||||||
|
|
||||||
from ..permissions import get_unlocked_packages
|
from .permissions import get_unlocked_packages
|
||||||
|
|
||||||
|
|
||||||
class CachedViewSetMixin:
|
class CachedViewSetMixin:
|
|
@ -1,5 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
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 _
|
||||||
|
|
||||||
|
@ -55,6 +56,10 @@ class Package(models.Model):
|
||||||
def package(self):
|
def package(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public(self):
|
||||||
|
return self.name in settings.PUBLIC_PACKAGES
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bounds(self):
|
def bounds(self):
|
||||||
if self.bottom is None:
|
if self.bottom is None:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
from ..mapdata.models import Source
|
from .models import Source
|
||||||
|
|
||||||
|
|
||||||
def get_unlocked_packages(request):
|
def get_unlocked_packages(request):
|
62
src/c3nav/mapdata/serializers.py
Normal file
62
src/c3nav/mapdata/serializers.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
from .models import Feature, Level, Package, Source
|
||||||
|
from .utils import sort_geojson
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryField(serializers.DictField):
|
||||||
|
"""
|
||||||
|
shapely geometry objects serialized using GeoJSON
|
||||||
|
"""
|
||||||
|
default_error_messages = {
|
||||||
|
'invalid': _('Invalid GeoJSON.')
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_representation(self, obj):
|
||||||
|
geojson = sort_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.'))
|
||||||
|
|
||||||
|
|
||||||
|
class LevelSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Level
|
||||||
|
fields = ('name', 'altitude', 'package')
|
||||||
|
|
||||||
|
|
||||||
|
class PackageSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Package
|
||||||
|
fields = ('name', 'home_repo', 'commit_id', 'depends', 'bounds', 'public')
|
||||||
|
readonly_fields = ('commit_id', )
|
||||||
|
|
||||||
|
|
||||||
|
class SourceSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Source
|
||||||
|
fields = ('name', 'package', 'bounds')
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureTypeSerializer(serializers.Serializer):
|
||||||
|
name = serializers.CharField()
|
||||||
|
title = serializers.CharField()
|
||||||
|
title_plural = serializers.CharField()
|
||||||
|
geomtype = serializers.CharField()
|
||||||
|
color = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureSerializer(serializers.ModelSerializer):
|
||||||
|
geometry = GeometryField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Feature
|
||||||
|
fields = ('name', 'package', 'feature_type', 'geometry')
|
|
@ -47,6 +47,7 @@ else:
|
||||||
|
|
||||||
debug_fallback = "runserver" in sys.argv
|
debug_fallback = "runserver" in sys.argv
|
||||||
DEBUG = config.getboolean('django', 'debug', fallback=debug_fallback)
|
DEBUG = config.getboolean('django', 'debug', fallback=debug_fallback)
|
||||||
|
DIRECT_EDITING = config.getboolean('c3nav', 'enable_editor', fallback=DEBUG)
|
||||||
PUBLIC_PACKAGES = [n for n in config.get('c3nav', 'public_packages', fallback='').split(',') if n]
|
PUBLIC_PACKAGES = [n for n in config.get('c3nav', 'public_packages', fallback='').split(',') if n]
|
||||||
|
|
||||||
EDITOR_HOSTERS = OrderedDict((name[7:], data) for name, data in config.items() if name.startswith('hoster:'))
|
EDITOR_HOSTERS = OrderedDict((name[7:], data) for name, data in config.items() if name.startswith('hoster:'))
|
||||||
|
@ -168,7 +169,7 @@ REST_FRAMEWORK = {
|
||||||
'ALLOWED_VERSIONS': ['v1'],
|
'ALLOWED_VERSIONS': ['v1'],
|
||||||
'DEFAULT_VERSION': 'v1',
|
'DEFAULT_VERSION': 'v1',
|
||||||
'DEFAULT_PERMISSION_CLASSES': (
|
'DEFAULT_PERMISSION_CLASSES': (
|
||||||
'c3nav.api.permissions.LockedMapFeatures',
|
'c3nav.mapdata.permissions.LockedMapFeatures',
|
||||||
),
|
),
|
||||||
'DEFAULT_FILTER_BACKENDS': (
|
'DEFAULT_FILTER_BACKENDS': (
|
||||||
'rest_framework.filters.DjangoFilterBackend',
|
'rest_framework.filters.DjangoFilterBackend',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue