remove recursive serialization in api and replace url root with list of all endpoints

This commit is contained in:
Laura Klünder 2016-10-11 17:29:02 +02:00
parent 9658de72a2
commit 4b97e3532f
6 changed files with 66 additions and 131 deletions

View file

@ -1,46 +0,0 @@
from collections import Iterable
from django.db.models.manager import BaseManager
from rest_framework import serializers
class RelatedNameField(serializers.DictField):
"""
give primary key
"""
def to_representation(self, obj):
if hasattr(obj, 'name'):
return obj.name
elif isinstance(obj, Iterable):
return tuple(self.to_representation(elem) for elem in obj)
elif isinstance(obj, BaseManager):
return tuple(self.to_representation(elem) for elem in obj.all())
return None
class RecursiveSerializerMixin(serializers.Serializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
request = self.context.get('request')
request_sparse = self.context['request_sparse'] = request is not None and request.GET.get('sparse')
sparse = self.context['sparse'] = request_sparse or self.context.get('sparse')
if sparse:
for name in getattr(self.Meta, 'sparse_exclude', ()):
value = self.fields.get(name)
if value is not None and isinstance(value, serializers.Serializer):
self.fields[name] = RelatedNameField()
if request_sparse:
for name in tuple(self.fields):
if name == 'url' or name.endswith('_url'):
self.fields.pop(name)
def sparse_context(self):
return {'request': self.context.get('request'), 'sparse': True}
def recursive_value(self, serializer, obj, *args, **kwargs):
if self.context.get('sparse'):
return RelatedNameField().to_representation(obj)
return serializer(obj, context=self.sparse_context(), *args, **kwargs).data

View file

@ -24,11 +24,3 @@
{% block branding %}
<span class="navbar-brand">c3nav API</span>
{% endblock %}
{% block description %}
{% if breadcrumblist|length == 1 %}
<p>Welcome to the c3nav RESTful API.</p>
<p><small><em>Add <code>?sparse=1</code> to any request to flatten its result.</em></small></p>
{% else %}{{ description }}{% endif %}
{% endblock %}

View file

@ -1,9 +1,16 @@
from rest_framework.routers import DefaultRouter
import re
from collections import OrderedDict
from compressor.utils.decorators import cached_property
from django.conf.urls import include, url
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.routers import SimpleRouter
from c3nav.editor.api import HosterViewSet, SubmitTaskViewSet
from c3nav.mapdata.api import FeatureTypeViewSet, FeatureViewSet, LevelViewSet, PackageViewSet, SourceViewSet
router = DefaultRouter()
router = SimpleRouter()
router.register(r'levels', LevelViewSet)
router.register(r'packages', PackageViewSet)
router.register(r'sources', SourceViewSet)
@ -12,4 +19,33 @@ router.register(r'features', FeatureViewSet)
router.register(r'hosters', HosterViewSet, base_name='hoster')
router.register(r'submittasks', SubmitTaskViewSet, base_name='submittask')
urlpatterns = router.urls
class APIRoot(GenericAPIView):
"""
Welcome to the c3nav RESTful API.
"""
def _format_pattern(self, pattern):
return re.sub(r'\(\?P<([^>]*[^>_])_?>[^)]+\)', r'{\1}', pattern)[1:-1]
@cached_property
def urls(self):
urls = OrderedDict()
for urlpattern in router.urls:
name = urlpattern.name
url = self._format_pattern(urlpattern.regex.pattern)
base = url.split('/', 1)[0]
if '-' in name:
urls.setdefault(base, OrderedDict())[name.split('-', 1)[1]] = url
else:
urls[name] = url
return urls
def get(self, request):
return Response(self.urls)
urlpatterns = [
url(r'^$', APIRoot.as_view()),
url(r'', include(router.urls)),
]