first stuff for custom positions

This commit is contained in:
Laura Klünder 2019-12-27 14:13:40 +01:00
parent e144156b8a
commit 407e3ba06b
12 changed files with 655 additions and 267 deletions

View file

@ -0,0 +1,56 @@
# Generated by Django 2.2.8 on 2019-12-27 12:51
import c3nav.mapdata.fields
import c3nav.mapdata.models.locations
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('mapdata', '0081_auto_20191225_1015'),
]
operations = [
migrations.CreateModel(
name='Position',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32, verbose_name='name')),
('secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_secret, max_length=32, unique=True, verbose_name='secret')),
('last_location_update', models.DateTimeField(null=True, verbose_name='last location update')),
('location_id', models.CharField(max_length=48, null=True, verbose_name='location')),
('api_secret', models.CharField(default=c3nav.mapdata.models.locations.get_position_api_secret, max_length=64, verbose_name='api secret')),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dynamic_positions', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Dynamic position',
'verbose_name_plural': 'Dynamic position',
'default_related_name': 'dynamic_positions',
},
),
migrations.CreateModel(
name='DynamicLocation',
fields=[
('locationslug_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='dynamic_locations', serialize=False, to='mapdata.LocationSlug')),
('title', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, fallback_value='{model} {pk}', plural_name='titles', verbose_name='Title')),
('can_search', models.BooleanField(default=True, verbose_name='can be searched')),
('can_describe', models.BooleanField(default=True, verbose_name='can describe')),
('icon', models.CharField(blank=True, help_text='any material icons name', max_length=32, null=True, verbose_name='icon')),
('label_override', c3nav.mapdata.fields.I18nField(blank=True, fallback_any=True, plural_name='label_overrides', verbose_name='Label override')),
('position_secret', models.CharField(blank=True, max_length=32, null=True, verbose_name='position secret')),
('access_restriction', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.AccessRestriction', verbose_name='Access Restriction')),
('groups', models.ManyToManyField(blank=True, related_name='dynamic_locations', to='mapdata.LocationGroup', verbose_name='Location Groups')),
('label_settings', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='dynamic_locations', to='mapdata.LabelSettings', verbose_name='label settings')),
],
options={
'verbose_name': 'Dynamic location',
'verbose_name_plural': 'Dynamic locations',
'default_related_name': 'dynamic_locations',
},
bases=('mapdata.locationslug', models.Model),
),
]

View file

@ -1,11 +1,14 @@
import string
from contextlib import suppress
from decimal import Decimal
from operator import attrgetter
from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import models
from django.db.models import FieldDoesNotExist, Prefetch
from django.urls import reverse
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _
@ -15,6 +18,7 @@ from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.grid import grid
from c3nav.mapdata.models.access import AccessRestrictionMixin
from c3nav.mapdata.models.base import SerializableMixin, TitledMixin
from c3nav.mapdata.utils.fields import LocationById
from c3nav.mapdata.utils.models import get_submodels
@ -452,3 +456,52 @@ class LabelSettings(SerializableMixin, models.Model):
verbose_name_plural = _('Label Settings')
default_related_name = 'labelsettings'
ordering = ('min_zoom', '-font_size')
class DynamicLocation(SpecificLocation, models.Model):
position_secret = models.CharField(_('position secret'), max_length=32, null=True, blank=True)
class Meta:
verbose_name = _('Dynamic location')
verbose_name_plural = _('Dynamic locations')
default_related_name = 'dynamic_locations'
"""
def _serialize(self, **kwargs):
result = super()._serialize(**kwargs)
return result
@property
def grid_square(self):
return grid.get_squares_for_bounds(self.geometry.bounds) or ''
def details_display(self, editor_url=True, **kwargs):
result = super().details_display(**kwargs)
if editor_url:
result['editor_url'] = reverse('editor.areas.edit', kwargs={'space': self.space_id, 'pk': self.pk})
return result
"""
def get_position_secret():
return get_random_string(32, string.ascii_letters+string.digits)
def get_position_api_secret():
return get_random_string(64, string.ascii_letters+string.digits)
class Position(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(_('name'), max_length=32)
secret = models.CharField(_('secret'), unique=True, max_length=32, default=get_position_secret)
last_location_update = models.DateTimeField(_('last location update'), null=True)
location_id = models.CharField(_('location'), null=True, max_length=48)
api_secret = models.CharField(_('api secret'), max_length=64, default=get_position_api_secret)
coordinates = LocationById()
class Meta:
verbose_name = _('Dynamic position')
verbose_name_plural = _('Dynamic position')
default_related_name = 'dynamic_positions'

View file

@ -3,7 +3,6 @@ import string
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models import Q
from django.urls import reverse
@ -15,7 +14,7 @@ from c3nav.mapdata.fields import I18nField
from c3nav.mapdata.models.geometry.level import LevelGeometryMixin
from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
from c3nav.mapdata.models.locations import SpecificLocation
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
from c3nav.mapdata.utils.fields import LocationById
from c3nav.mapdata.utils.models import get_submodels
from c3nav.site.tasks import send_report_notification
@ -24,39 +23,6 @@ def get_report_secret():
return get_random_string(32, string.ascii_letters)
class LocationById():
def __init__(self):
super().__init__()
self.name = None
self.cached_id = None
self.cached_value = None
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner=None):
value_id = getattr(instance, self.name+'_id')
if value_id is None:
self.cached_pk = None
self.cached_value = None
return None
if value_id == self.cached_id:
return self.cached_value
value = get_location_by_id_for_request(value_id, getattr(instance, 'request', None))
if value is None:
raise ObjectDoesNotExist
self.cached_id = value_id
self.cached_value = value
return value
def __set__(self, instance, value):
self.cached_id = value.pk
self.cached_value = value
setattr(instance, self.name+'_id', value.pk)
class Report(models.Model):
CATEGORIES = (
('location-issue', _('location issue')),

View file

@ -0,0 +1,35 @@
from django.core.exceptions import ObjectDoesNotExist
class LocationById():
def __init__(self):
super().__init__()
self.name = None
self.cached_id = None
self.cached_value = None
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner=None):
value_id = getattr(instance, self.name+'_id')
if value_id is None:
self.cached_pk = None
self.cached_value = None
return None
if value_id == self.cached_id:
return self.cached_value
from c3nav.mapdata.utils.locations import get_location_by_id_for_request
value = get_location_by_id_for_request(value_id, getattr(instance, 'request', None))
if value is None:
raise ObjectDoesNotExist
self.cached_id = value_id
self.cached_value = value
return value
def __set__(self, instance, value):
self.cached_id = value.pk
self.cached_value = value
setattr(instance, self.name+'_id', value.pk)