wrap around ORM in editor api
This commit is contained in:
parent
7e78bf0550
commit
344ab790a3
3 changed files with 30 additions and 9 deletions
|
@ -7,7 +7,7 @@ from rest_framework.response import Response
|
|||
from rest_framework.viewsets import ViewSet
|
||||
from shapely.ops import cascaded_union
|
||||
|
||||
from c3nav.mapdata.models import Level, Space
|
||||
from c3nav.editor.models import ChangeSet
|
||||
|
||||
|
||||
class EditorViewSet(ViewSet):
|
||||
|
@ -16,7 +16,7 @@ class EditorViewSet(ViewSet):
|
|||
/geometries/ returns a list of geojson features, you have to specify ?level=<id> or ?space=<id>
|
||||
/geometrystyles/ returns styling information for all geometry types
|
||||
"""
|
||||
def _get_level_geometries(self, level: Level):
|
||||
def _get_level_geometries(self, level):
|
||||
buildings = level.buildings.all()
|
||||
buildings_geom = cascaded_union([building.geometry for building in buildings])
|
||||
spaces = {space.id: space for space in level.spaces.all()}
|
||||
|
@ -44,10 +44,11 @@ class EditorViewSet(ViewSet):
|
|||
results.extend(spaces.values())
|
||||
return results
|
||||
|
||||
def _get_levels_pk(self, level):
|
||||
def _get_levels_pk(self, request, level):
|
||||
Level = request.changeset.wrap('Level')
|
||||
levels_under = ()
|
||||
levels_on_top = ()
|
||||
lower_level = level.lower().first()
|
||||
lower_level = level.lower(Level).first()
|
||||
primary_levels = (level,) + ((lower_level,) if lower_level else ())
|
||||
secondary_levels = Level.objects.filter(on_top_of__in=primary_levels).values_list('pk', 'on_top_of')
|
||||
if lower_level:
|
||||
|
@ -59,6 +60,11 @@ class EditorViewSet(ViewSet):
|
|||
|
||||
@list_route(methods=['get'])
|
||||
def geometries(self, request, *args, **kwargs):
|
||||
request.changeset = ChangeSet.get_for_request(request)
|
||||
|
||||
Level = request.changeset.wrap('Level')
|
||||
Space = request.changeset.wrap('Space')
|
||||
|
||||
level = request.GET.get('level')
|
||||
space = request.GET.get('space')
|
||||
if level is not None:
|
||||
|
@ -66,7 +72,7 @@ class EditorViewSet(ViewSet):
|
|||
raise ValidationError('Only level or space can be specified.')
|
||||
level = get_object_or_404(Level, pk=level)
|
||||
|
||||
levels, levels_on_top, levels_under = self._get_levels_pk(level)
|
||||
levels, levels_on_top, levels_under = self._get_levels_pk(request, level)
|
||||
levels = Level.objects.filter(pk__in=levels).prefetch_related('buildings', 'spaces', 'doors',
|
||||
'spaces__groups', 'spaces__holes',
|
||||
'spaces__columns')
|
||||
|
@ -90,7 +96,7 @@ class EditorViewSet(ViewSet):
|
|||
doors = [door for door in level.doors.all() if door.geometry.intersects(space.geometry)]
|
||||
doors_space_geom = cascaded_union([door.geometry for door in doors]+[space.geometry])
|
||||
|
||||
levels, levels_on_top, levels_under = self._get_levels_pk(level.primary_level)
|
||||
levels, levels_on_top, levels_under = self._get_levels_pk(request, level.primary_level)
|
||||
other_spaces = Space.objects.filter(level__pk__in=levels).prefetch_related('groups')
|
||||
other_spaces = [s for s in other_spaces
|
||||
if s.geometry.intersects(doors_space_geom) and s.pk != space.pk]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from collections import Iterable
|
||||
from django.db import models
|
||||
from django.db.models import Manager
|
||||
|
||||
|
@ -34,7 +35,8 @@ class BaseWrapper:
|
|||
elif isinstance(value, type) and issubclass(value, Exception):
|
||||
pass
|
||||
elif callable(value) and name not in self._allowed_callables:
|
||||
raise TypeError('Can not call %s.%s wrapped!' % (self._obj, name))
|
||||
if not isinstance(self, ModelInstanceWrapper) or hasattr(models.Model, name):
|
||||
raise TypeError('Can not call %s.%s wrapped!' % (self._obj, name))
|
||||
|
||||
# print(self._obj, name, type(value), value)
|
||||
return value
|
||||
|
@ -110,6 +112,9 @@ class BaseQueryWrapper(BaseWrapper):
|
|||
def filter(self, *args, **kwargs):
|
||||
kwargs = {name: (value._obj if isinstance(value, ModelInstanceWrapper) else value)
|
||||
for name, value in kwargs.items()}
|
||||
kwargs = {name: ([(item._obj if isinstance(item, ModelInstanceWrapper) else item) for item in value]
|
||||
if isinstance(value, Iterable) else value)
|
||||
for name, value in kwargs.items()}
|
||||
return self._wrap_queryset(self._obj.filter(*args, **kwargs))
|
||||
|
||||
def count(self):
|
||||
|
@ -118,6 +123,12 @@ class BaseQueryWrapper(BaseWrapper):
|
|||
def values_list(self, *args, flat=False):
|
||||
return self._obj.values_list(*args, flat=flat)
|
||||
|
||||
def first(self):
|
||||
first = self._obj.first()
|
||||
if first is not None:
|
||||
first = self._wrap_instance(first)
|
||||
return first
|
||||
|
||||
def __iter__(self):
|
||||
return iter([instance for instance in self._obj])
|
||||
|
||||
|
|
|
@ -28,14 +28,18 @@ class Level(SpecificLocation, EditorFormMixin, models.Model):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def lower(self):
|
||||
def lower(self, level_model=None):
|
||||
if self.on_top_of_id is not None:
|
||||
raise TypeError
|
||||
if level_model is not None:
|
||||
Level = level_model
|
||||
return Level.objects.filter(altitude__lt=self.altitude, on_top_of__isnull=True).order_by('-altitude')
|
||||
|
||||
def higher(self):
|
||||
def higher(self, level_model=None):
|
||||
if self.on_top_of_id is not None:
|
||||
raise TypeError
|
||||
if level_model is not None:
|
||||
Level = level_model
|
||||
return Level.objects.filter(altitude__gt=self.altitude, on_top_of__isnull=True).order_by('altitude')
|
||||
|
||||
@property
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue