def __init__(self, *args, space_id=None, request=None, geometry_editable=False, is_json=False, **kwargs): self.request = request super().__init__(*args, **kwargs) creating = not self.instance.pk if hasattr(self.instance, 'author_id'): if self.instance.author_id is None: self.instance.author = request.user if 'geometry' in self.fields: if not geometry_editable: # can't see this geometry in editor self.fields.pop('geometry') else: # hide geometry widget self.fields['geometry'].widget = HiddenInput() if not creating: self.initial['geometry'] = json.dumps( mapping(self.instance.geometry), separators=(',', ':')) if self._meta.model.__name__ == 'Source' and self.request.user.is_superuser: Source = self.request.changeset.wrap_model('Source') sources = { s['name']: s for s in Source.objects.all().values('name', 'access_restriction_id', 'left', 'bottom', 'right', 'top') } used_names = set(sources.keys()) all_names = set(os.listdir(settings.SOURCES_ROOT)) if not creating: used_names.remove(self.instance.name) all_names.add(self.instance.name) self.fields['name'].widget = Select(choices=tuple( (s, s) for s in sorted(all_names - used_names))) if creating: for s in sources.values(): s['access_restriction'] = s['access_restriction_id'] del s['access_restriction_id'] self.fields['copy_from'] = ChoiceField(choices=tuple( (('', '---------'), )) + tuple( (json.dumps(sources[name], separators=(',', ':'), cls=DjangoJSONEncoder), name) for name in sorted(used_names)), required=False) self.fields['fixed_x'] = DecimalField(label='fixed x', required=False, max_digits=7, decimal_places=3, initial=0) self.fields['fixed_y'] = DecimalField(label='fixed y', required=False, max_digits=7, decimal_places=3, initial=0) self.fields['scale_x'] = DecimalField(label='scale x (m/px)', required=False, max_digits=7, decimal_places=3, initial=1) self.fields['scale_y'] = DecimalField(label='scale y (m/px)', required=False, max_digits=7, decimal_places=3, initial=1) self.fields['lock_aspect'] = BooleanField( label='lock aspect ratio', required=False, initial=True) self.fields['lock_scale'] = BooleanField( label='lock scale (for moving)', required=False, initial=True) self.fields.move_to_end('lock_scale', last=False) self.fields.move_to_end('lock_aspect', last=False) self.fields.move_to_end('scale_y', last=False) self.fields.move_to_end('scale_x', last=False) self.fields.move_to_end('fixed_y', last=False) self.fields.move_to_end('fixed_x', last=False) self.fields.move_to_end('access_restriction', last=False) if creating: self.fields.move_to_end('copy_from', last=False) self.fields.move_to_end('name', last=False) if self._meta.model.__name__ == 'AccessRestriction': AccessRestrictionGroup = self.request.changeset.wrap_model( 'AccessRestrictionGroup') self.fields['groups'].label_from_instance = lambda obj: obj.title self.fields[ 'groups'].queryset = AccessRestrictionGroup.qs_for_request( self.request) elif 'groups' in self.fields: LocationGroupCategory = self.request.changeset.wrap_model( 'LocationGroupCategory') kwargs = { 'allow_' + self._meta.model._meta.default_related_name: True } categories = LocationGroupCategory.objects.filter( **kwargs).prefetch_related('groups') if self.instance.pk: instance_groups = tuple( self.instance.groups.values_list('pk', flat=True)) else: instance_groups = () self.fields.pop('groups') for category in categories: choices = tuple((str(group.pk), group.title) for group in sorted(category.groups.all(), key=self.sort_group)) category_groups = set(group.pk for group in category.groups.all()) initial = tuple( str(pk) for pk in instance_groups if pk in category_groups) if category.single: name = 'group_' + category.name initial = initial[0] if initial else '' choices = (('', '---'), ) + choices field = ChoiceField(label=category.title, required=False, initial=initial, choices=choices, help_text=category.help_text) else: name = 'groups_' + category.name field = MultipleChoiceField(label=category.title_plural, required=False, initial=initial, choices=choices, help_text=category.help_text) self.fields[name] = field if 'label_settings' in self.fields: self.fields.move_to_end('label_settings') for field in tuple(self.fields.keys()): if field.startswith('label_override'): self.fields.move_to_end(field) if 'category' in self.fields: self.fields['category'].label_from_instance = attrgetter('title') if 'label_settings' in self.fields: self.fields['label_settings'].label_from_instance = attrgetter( 'title') if 'access_restriction' in self.fields: AccessRestriction = self.request.changeset.wrap_model( 'AccessRestriction') self.fields[ 'access_restriction'].label_from_instance = lambda obj: obj.title self.fields[ 'access_restriction'].queryset = AccessRestriction.qs_for_request( self.request) if 'base_mapdata_accessible' in self.fields: if not request.user.is_superuser: self.fields['base_mapdata_accessible'].disabled = True if space_id and 'target_space' in self.fields: Space = self.request.changeset.wrap_model('Space') 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 self.fields[space_field].queryset = space_qs self.redirect_slugs = None self.add_redirect_slugs = None self.remove_redirect_slugs = None if 'slug' in self.fields: self.redirect_slugs = sorted( self.instance.redirects.values_list('slug', flat=True)) self.fields['redirect_slugs'] = CharField( label=_('Redirecting Slugs (comma seperated)'), required=False, initial=','.join(self.redirect_slugs)) self.fields.move_to_end('redirect_slugs', last=False) self.fields.move_to_end('slug', last=False) if 'from_node' in self.fields: self.fields['from_node'].widget = HiddenInput() if 'to_node' in self.fields: self.fields['to_node'].widget = HiddenInput() if 'data' in self.fields and 'data' in self.initial: self.initial['data'] = json.dumps(self.initial['data']) self.is_json = is_json self.missing_fields = tuple( (name, field) for name, field in self.fields.items() if name not in self.data and not field.required)