remove name field from most mapdata models

This commit is contained in:
Laura Klünder 2017-05-05 16:21:48 +02:00
parent baecf08aea
commit 89ab60b395
10 changed files with 96 additions and 39 deletions

View file

@ -9,5 +9,5 @@ urlpatterns = [
url(r'^mapitems/(?P<mapitem_type>[^/]+)/list/$', list_mapitems, name='editor.mapitems'),
url(r'^mapitems/(?P<mapitem_type>[^/]+)/list/(?P<level>[^/]+)/$', list_mapitems, name='editor.mapitems.level'),
url(r'^mapitems/(?P<mapitem_type>[^/]+)/add/$', edit_mapitem, name='editor.mapitems.add'),
url(r'^mapitems/(?P<mapitem_type>[^/]+)/edit/(?P<name>[^/]+)/$', edit_mapitem, name='editor.mapitems.edit'),
url(r'^mapitems/(?P<mapitem_type>[^/]+)/edit/(?P<id>[^/]+)/$', edit_mapitem, name='editor.mapitems.edit'),
]

View file

@ -4,11 +4,12 @@ from django.http.response import Http404
from django.shortcuts import get_object_or_404, redirect, render
from c3nav.access.apply import can_access, filter_queryset_by_access
from c3nav.mapdata.models import AreaLocation
from c3nav.mapdata.models import AreaLocation, Level
from c3nav.mapdata.models.base import FEATURE_TYPES
def list_mapitemtypes(request, level):
level = get_object_or_404()
def get_item_count(mapitemtype):
if hasattr(mapitemtype, 'level'):
return filter_queryset_by_access(request, mapitemtype.objects.filter(level__name=level)).count()
@ -43,11 +44,13 @@ def list_mapitems(request, mapitem_type, level=None):
return redirect('editor.mapitems', mapitem_type=mapitem_type)
queryset = mapitemtype.objects.all().order_by('name')
if level is not None:
level = get_object_or_404(Level, level)
if hasattr(mapitemtype, 'level'):
queryset = queryset.filter(level__name=level)
queryset = queryset.filter(level=level)
elif hasattr(mapitemtype, 'levels'):
queryset = queryset.filter(levels__name=level)
queryset = queryset.filter(levels=level)
queryset = filter_queryset_by_access(request, queryset)
@ -62,7 +65,7 @@ def list_mapitems(request, mapitem_type, level=None):
'has_levels': hasattr(mapitemtype, 'levels'),
'has_altitude': hasattr(mapitemtype, 'altitude'),
'has_intermediate': hasattr(mapitemtype, 'intermediate'),
'level': level,
'level': level.id,
'items': queryset,
})

View file

@ -4,6 +4,7 @@ import mimetypes
import hashlib
from collections import OrderedDict
from django.http import Http404, HttpResponse, HttpResponseNotModified
from django.shortcuts import get_object_or_404
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
@ -48,10 +49,7 @@ class GeometryViewSet(ViewSet):
level = None
if 'level' in request.GET:
levels_cached = get_levels_cached()
level_name = request.GET['level']
if level_name in levels_cached:
level = levels_cached[level_name]
level = get_object_or_404(Level, id=request.GET['level'])
cache_key = '__'.join((
','.join([str(i) for i in types]),
@ -78,7 +76,7 @@ class GeometryViewSet(ViewSet):
else:
queryset = queryset.none()
queryset = filter_queryset_by_access(request, queryset)
queryset = queryset.order_by('name')
queryset = queryset.order_by('id')
for field_name in ('level', 'crop_to_level', 'elevator'):
if hasattr(mapitemtype, field_name):
@ -105,9 +103,7 @@ class LevelViewSet(CachedReadOnlyViewSetMixin, ReadOnlyModelViewSet):
"""
queryset = Level.objects.all()
serializer_class = LevelSerializer
lookup_field = 'name'
lookup_value_regex = '[^/]+'
ordering = ('altitude',)
lookup_field = 'id'
class SourceViewSet(CachedReadOnlyViewSetMixin, ReadOnlyModelViewSet):
@ -116,9 +112,7 @@ class SourceViewSet(CachedReadOnlyViewSetMixin, ReadOnlyModelViewSet):
"""
queryset = Source.objects.all()
serializer_class = SourceSerializer
lookup_field = 'name'
lookup_value_regex = '[^/]+'
ordering = ('name',)
lookup_field = 'id'
def get_queryset(self):
return filter_queryset_by_access(self.request, super().get_queryset().all())
@ -140,11 +134,11 @@ class LocationViewSet(ViewSet):
List and retrieve locations
"""
# We don't cache this, because it depends on access_list
lookup_field = 'name'
lookup_field = 'location_id'
@staticmethod
def _filter(queryset):
return queryset.filter(can_search=True).order_by('name')
return queryset.filter(can_search=True).order_by('id')
def list(self, request, **kwargs):
etag = hashlib.sha256(json.dumps({
@ -168,8 +162,8 @@ class LocationViewSet(ViewSet):
response['Cache-Control'] = 'no-cache'
return response
def retrieve(self, request, name=None, **kwargs):
location = get_location(request, name)
def retrieve(self, request, location_id=None, **kwargs):
location = get_location(request, location_id)
if location is None:
raise Http404
return Response(location.to_location_json())

View file

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-05-05 13:34
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('mapdata', '0054_remove_obstacle_crop_to_level'),
]
operations = [
migrations.RenameField(
model_name='arealocation',
old_name='name',
new_name='slug',
),
migrations.RenameField(
model_name='locationgroup',
old_name='name',
new_name='slug',
),
migrations.RemoveField(
model_name='area',
name='name',
),
migrations.RemoveField(
model_name='building',
name='name',
),
migrations.RemoveField(
model_name='door',
name='name',
),
migrations.RemoveField(
model_name='hole',
name='name',
),
migrations.RemoveField(
model_name='lineobstacle',
name='name',
),
migrations.RemoveField(
model_name='obstacle',
name='name',
),
migrations.RemoveField(
model_name='stair',
name='name',
),
migrations.RemoveField(
model_name='stuffedarea',
name='name',
),
]

View file

@ -32,8 +32,6 @@ class FeatureBase(ModelBase):
class Feature(models.Model, metaclass=FeatureBase):
name = models.SlugField(_('Name'), unique=True, max_length=50)
EditorForm = None
@property
@ -71,7 +69,7 @@ class GeometryFeature(Feature):
def get_geojson_properties(self):
return OrderedDict((
('type', self.__class__.__name__.lower()),
('name', self.name),
('id', self.id),
))
def to_geojson(self):

View file

@ -19,7 +19,7 @@ class LevelFeature(GeometryFeature):
def get_geojson_properties(self):
result = super().get_geojson_properties()
result['level'] = self.level.name
result['level'] = self.level.id
return result
@ -34,7 +34,7 @@ class AreaFeature(GeometryFeature):
def get_geojson_properties(self):
result = super().get_geojson_properties()
result['area'] = self.area.name
result['area'] = self.area.id
return result
@ -124,8 +124,8 @@ class Stair(AreaFeature):
('properties', OrderedDict((
('type', 'shadow'),
('original_type', self.__class__.__name__.lower()),
('original_name', self.name),
('area', self.area.name),
('original_id', self.id),
('area', self.area.id),
))),
('geometry', format_geojson(mapping(shadow), round=False)),
))

View file

@ -25,7 +25,8 @@ class Location:
def to_location_json(self):
return OrderedDict((
('id', self.location_id),
('id', self.id),
('location_id', self.location_id),
('title', str(self.title)),
('subtitle', str(self.subtitle)),
))
@ -35,6 +36,7 @@ class Location:
class LocationModelMixin(Location):
def get_geojson_properties(self):
result = super().get_geojson_properties()
result['slug'] = self.slug
result['titles'] = OrderedDict(sorted(self.titles.items()))
return result
@ -44,6 +46,7 @@ class LocationModelMixin(Location):
class LocationGroup(LocationModelMixin, Feature):
slug = models.SlugField(_('Name'), unique=True, max_length=50)
titles = JSONField()
can_search = models.BooleanField(default=True, verbose_name=_('can be searched'))
can_describe = models.BooleanField(default=True, verbose_name=_('can be used to describe a position'))
@ -58,14 +61,14 @@ class LocationGroup(LocationModelMixin, Feature):
@cached_property
def location_id(self):
return 'g:'+self.name
return 'g:'+self.slug
def get_in_levels(self):
last_update = get_last_mapdata_update()
if last_update is None:
return self._get_in_levels()
cache_key = 'c3nav__mapdata__locationgroup__in_levels__'+last_update.isoformat()+'__'+self.name,
cache_key = 'c3nav__mapdata__locationgroup__in_levels__'+last_update.isoformat()+'__'+str(self.id),
in_levels = cache.get(cache_key)
if not in_levels:
in_levels = self._get_in_levels()
@ -115,6 +118,7 @@ class AreaLocation(LocationModelMixin, LevelFeature):
('needs_permission', _('Excluded, needs permission to include')),
)
slug = models.SlugField(_('Name'), unique=True, max_length=50)
location_type = models.CharField(max_length=20, choices=LOCATION_TYPES, verbose_name=_('Location Type'))
titles = JSONField()
groups = models.ManyToManyField(LocationGroup, verbose_name=_('Location Groups'), blank=True)
@ -137,14 +141,14 @@ class AreaLocation(LocationModelMixin, LevelFeature):
@cached_property
def location_id(self):
return self.name
return self.slug
def get_in_areas(self):
last_update = get_last_mapdata_update()
if last_update is None:
return self._get_in_areas()
cache_key = 'c3nav__mapdata__location__in_areas__'+last_update.isoformat()+'__'+self.name,
cache_key = 'c3nav__mapdata__location__in_areas__'+last_update.isoformat()+'__'+str(self.id),
in_areas = cache.get(cache_key)
if not in_areas:
in_areas = self._get_in_areas()

View file

@ -8,6 +8,7 @@ class Source(Feature):
"""
A map source, images of levels that can be useful as backgrounds for the map editor
"""
name = models.SlugField(_('Name'), unique=True, max_length=50)
bottom = models.DecimalField(_('bottom coordinate'), max_digits=6, decimal_places=2)
left = models.DecimalField(_('left coordinate'), max_digits=6, decimal_places=2)
top = models.DecimalField(_('top coordinate'), max_digits=6, decimal_places=2)

View file

@ -8,8 +8,8 @@ from c3nav.mapdata.models.locations import PointLocation
from c3nav.mapdata.utils.cache import get_levels_cached
def get_location(request, name):
match = re.match('^c:(?P<level>[a-z0-9-_]+):(?P<x>[0-9]+):(?P<y>[0-9]+)$', name)
def get_location(request, location_id):
match = re.match('^c:(?P<level>[a-z0-9-_]+):(?P<x>[0-9]+):(?P<y>[0-9]+)$', location_id)
if match:
levels = get_levels_cached()
level = levels.get(match.group('level'))
@ -17,11 +17,11 @@ def get_location(request, name):
return None
return PointLocation(level=level, x=int(match.group('x'))/100, y=int(match.group('y'))/100, request=request)
if name.startswith('g:'):
queryset = LocationGroup.objects.filter(Q(name=name[2:], can_search=True))
if location_id.startswith('g:'):
queryset = LocationGroup.objects.filter(Q(slug=location_id[2:], can_search=True))
return filter_queryset_by_access(request, queryset).first()
return filter_arealocations_by_access(request, AreaLocation.objects.filter(name=name, can_search=True)).first()
return filter_arealocations_by_access(request, AreaLocation.objects.filter(slug=location_id, can_search=True)).first()
def filter_words(queryset, words):

View file

@ -6,10 +6,10 @@ from c3nav.mapdata.models import Level, Source
class LevelSerializer(serializers.ModelSerializer):
class Meta:
model = Level
fields = ('name', 'altitude')
fields = ('id', 'name', 'altitude')
class SourceSerializer(serializers.ModelSerializer):
class Meta:
model = Source
fields = ('name', 'bounds')
fields = ('id', 'name', 'bounds')