edit route descriptions: only suggest neighbor spaces

This commit is contained in:
Laura Klünder 2017-12-19 01:49:54 +01:00
parent 0a0bf9972a
commit b32b5c2beb
2 changed files with 55 additions and 5 deletions

View file

@ -1,8 +1,11 @@
import json
import operator
from functools import reduce
from itertools import chain
from django.core.cache import cache
from django.core.exceptions import FieldDoesNotExist
from django.db.models import Q
from django.forms import (BooleanField, CharField, ChoiceField, Form, ModelChoiceField, ModelForm, MultipleChoiceField,
ValidationError)
from django.forms.widgets import HiddenInput
@ -13,10 +16,11 @@ from c3nav.editor.models import ChangeSet, ChangeSetUpdate
from c3nav.mapdata.fields import GeometryField
from c3nav.mapdata.forms import I18nModelFormMixin
from c3nav.mapdata.models import GraphEdge
from c3nav.mapdata.models.access import AccessPermission
class EditorFormBase(I18nModelFormMixin, ModelForm):
def __init__(self, *args, request=None, **kwargs):
def __init__(self, *args, space_id=None, request=None, **kwargs):
self.request = request
super().__init__(*args, **kwargs)
creating = not self.instance.pk
@ -71,9 +75,36 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
self.fields['access_restriction'].label_from_instance = lambda obj: obj.title
self.fields['access_restriction'].queryset = AccessRestriction.qs_for_request(self.request)
if 'target_space' in self.fields:
if space_id and 'target_space' in self.fields:
Space = self.request.changeset.wrap_model('Space')
space_qs = Space.qs_for_request(self.request)
GraphNode = self.request.changeset.wrap_model('GraphNode')
GraphEdge = self.request.changeset.wrap_model('GraphEdge')
cache_key = 'editor:neighbor_spaces:%s:%s%d' % (
self.request.changeset.raw_cache_key_by_changes,
AccessPermission.cache_key_for_request(request, with_update=False),
space_id
)
other_spaces = cache.get(cache_key, None)
if other_spaces is None:
AccessPermission.cache_key_for_request(request, with_update=False) + ':' + str(request.user.pk or 0)
space_nodes = set(GraphNode.objects.filter(space_id=space_id).values_list('pk', flat=True))
space_edges = GraphEdge.objects.filter(
Q(from_node_id__in=space_nodes) | Q(to_node_id__in=space_nodes)
).values_list('from_node_id', 'to_node_id')
other_nodes = set(chain(*space_edges)) - space_nodes
other_spaces = set(GraphNode.objects.filter(pk__in=other_nodes).values_list('space_id', flat=True))
other_spaces.discard(space_id)
cache.set(cache_key, other_spaces, 900)
for space_field in ('origin_space', 'target_space'):
other_space_id = getattr(self.instance, space_field+'_id', None)
if other_space_id:
other_spaces.add(other_space_id)
space_qs = Space.qs_for_request(self.request).filter(pk__in=other_spaces)
for space_field in ('origin_space', 'target_space'):
if space_field in self.fields:
self.fields[space_field].label_from_instance = lambda obj: obj.title

View file

@ -142,6 +142,7 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
'geomtype': model._meta.get_field('geometry').geomtype,
})
space_id = None
if model == Level:
ctx.update({
'level': obj,
@ -183,6 +184,7 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk),
})
elif hasattr(model, 'space'):
space_id = space.pk
if not new:
space = obj.space
ctx.update({
@ -234,7 +236,8 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
ctx['obj_title'] = obj.title
return render(request, 'editor/delete.html', ctx)
form = model.EditorForm(instance=model() if new else obj, data=request.POST, request=request)
form = model.EditorForm(instance=model() if new else obj, data=request.POST,
request=request, space_id=space_id)
if form.is_valid():
# Update/create objects
obj = form.save(commit=False)
@ -266,7 +269,7 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
messages.error(request, _('You can not edit changes on this changeset.'))
else:
form = model.EditorForm(instance=obj, request=request)
form = model.EditorForm(instance=obj, request=request, space_id=space_id)
ctx.update({
'form': form,
@ -319,12 +322,28 @@ def list_objects(request, model=None, level=None, space=None, explicit_edit=Fals
sub_qs = Space.objects.filter(Space.q_for_request(request)).select_related('level').defer('geometry')
space = get_object_or_404(sub_qs, pk=space)
queryset = queryset.filter(space=space)
try:
model._meta.get_field('geometry')
except FieldDoesNotExist:
pass
else:
queryset = queryset.defer('geometry')
try:
model._meta.get_field('origin_space')
except FieldDoesNotExist:
pass
else:
queryset = queryset.select_related('origin_space')
try:
model._meta.get_field('target_space')
except FieldDoesNotExist:
pass
else:
queryset = queryset.select_related('target_space')
ctx.update({
'levels': Level.objects.filter(Level.q_for_request(request), on_top_of__isnull=True),
'level': space.level,