2016-10-12 15:25:00 +02:00
|
|
|
from collections import OrderedDict
|
2017-05-07 12:06:13 +02:00
|
|
|
|
2017-10-19 13:55:35 +02:00
|
|
|
from django.core.cache import cache
|
2017-05-09 13:32:32 +02:00
|
|
|
from django.db import models
|
2017-12-20 23:05:58 +01:00
|
|
|
from django.db.models import Q
|
2017-11-02 13:35:58 +01:00
|
|
|
from django.utils.translation import get_language, get_language_info
|
2022-04-03 16:33:43 +02:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2017-07-10 13:01:35 +02:00
|
|
|
|
2017-11-30 00:43:39 +01:00
|
|
|
from c3nav.mapdata.fields import I18nField
|
2017-10-19 13:55:35 +02:00
|
|
|
from c3nav.mapdata.models import MapUpdate
|
2016-10-12 15:25:00 +02:00
|
|
|
|
2016-11-27 23:51:44 +01:00
|
|
|
|
2017-05-11 22:40:48 +02:00
|
|
|
class SerializableMixin(models.Model):
|
2019-12-10 18:55:09 +01:00
|
|
|
_affected_by_changeset = None
|
|
|
|
|
2017-05-09 12:50:32 +02:00
|
|
|
class Meta:
|
|
|
|
abstract = True
|
2017-05-11 19:36:49 +02:00
|
|
|
|
|
|
|
def serialize(self, **kwargs):
|
|
|
|
return self._serialize(**kwargs)
|
|
|
|
|
2017-05-11 21:30:29 +02:00
|
|
|
@classmethod
|
|
|
|
def serialize_type(cls, **kwargs):
|
|
|
|
return OrderedDict((
|
|
|
|
('name', cls.__name__.lower()),
|
|
|
|
('name_plural', cls._meta.default_related_name),
|
|
|
|
('title', str(cls._meta.verbose_name)),
|
|
|
|
('title_plural', str(cls._meta.verbose_name_plural)),
|
|
|
|
))
|
|
|
|
|
2017-05-11 19:36:49 +02:00
|
|
|
def _serialize(self, include_type=False, **kwargs):
|
2018-12-27 16:07:07 +01:00
|
|
|
result = {}
|
2017-05-11 19:36:49 +02:00
|
|
|
if include_type:
|
|
|
|
result['type'] = self.__class__.__name__.lower()
|
2017-06-16 18:19:52 +02:00
|
|
|
result['id'] = self.pk
|
2017-05-11 19:36:49 +02:00
|
|
|
return result
|
2017-05-11 22:40:48 +02:00
|
|
|
|
2018-09-19 19:08:47 +02:00
|
|
|
def details_display(self, **kwargs):
|
2017-11-02 13:35:58 +01:00
|
|
|
return {
|
2017-11-28 11:03:22 +01:00
|
|
|
'id': self.pk,
|
2017-11-02 13:35:58 +01:00
|
|
|
'display': [
|
2017-11-30 01:10:49 +01:00
|
|
|
(_('Type'), str(self.__class__._meta.verbose_name)),
|
|
|
|
(_('ID'), str(self.pk)),
|
2017-11-02 13:35:58 +01:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2018-12-25 17:39:40 +01:00
|
|
|
def get_geometry(self, detailed_geometry=True):
|
|
|
|
return None
|
|
|
|
|
2017-05-16 18:11:33 +02:00
|
|
|
@property
|
|
|
|
def title(self):
|
2017-06-21 12:47:28 +02:00
|
|
|
return self._meta.verbose_name + ' ' + str(self.id)
|
2017-05-26 21:25:54 +02:00
|
|
|
|
2017-12-20 23:05:58 +01:00
|
|
|
@classmethod
|
|
|
|
def qs_for_request(cls, request, allow_none=False):
|
|
|
|
return cls.objects.filter(cls.q_for_request(request, allow_none=allow_none))
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def q_for_request(cls, *args, **kwargs):
|
|
|
|
return Q()
|
|
|
|
|
2017-05-26 21:25:54 +02:00
|
|
|
|
2017-07-10 13:01:35 +02:00
|
|
|
class TitledMixin(SerializableMixin, models.Model):
|
2017-11-30 15:26:06 +01:00
|
|
|
title = I18nField(_('Title'), plural_name='titles', blank=True, fallback_any=True, fallback_value='{model} {pk}')
|
2017-07-10 13:01:35 +02:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
2017-10-27 15:05:41 +02:00
|
|
|
def serialize(self, **kwargs):
|
|
|
|
result = super().serialize(**kwargs)
|
2017-07-10 13:01:35 +02:00
|
|
|
return result
|
|
|
|
|
2017-11-27 15:01:58 +01:00
|
|
|
def _serialize(self, detailed=True, **kwargs):
|
|
|
|
result = super()._serialize(detailed=detailed, **kwargs)
|
|
|
|
if detailed:
|
|
|
|
result['titles'] = self.titles
|
2023-12-11 20:49:50 +01:00
|
|
|
result['title'] = self.title
|
2017-07-10 13:01:35 +02:00
|
|
|
return result
|
|
|
|
|
2019-12-26 12:11:51 +01:00
|
|
|
@property
|
|
|
|
def other_titles(self):
|
|
|
|
return tuple(title for lang, title in self.titles.items() if lang != get_language())
|
|
|
|
|
2018-09-19 19:08:47 +02:00
|
|
|
def details_display(self, **kwargs):
|
|
|
|
result = super().details_display(**kwargs)
|
2017-11-02 13:35:58 +01:00
|
|
|
for lang, title in sorted(self.titles.items(), key=lambda item: item[0] != get_language()):
|
|
|
|
language = _('Title ({lang})').format(lang=get_language_info(lang)['name_translated'])
|
|
|
|
result['display'].append((language, title))
|
|
|
|
return result
|
|
|
|
|
2024-09-16 13:21:29 +02:00
|
|
|
def __str__(self):
|
|
|
|
return str(self.title)
|
|
|
|
|
2017-07-10 13:01:35 +02:00
|
|
|
|
2017-05-26 21:25:54 +02:00
|
|
|
class BoundsMixin(SerializableMixin, models.Model):
|
|
|
|
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)
|
|
|
|
right = models.DecimalField(_('right coordinate'), max_digits=6, decimal_places=2)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def max_bounds(cls):
|
2017-10-23 22:49:45 +02:00
|
|
|
cache_key = 'mapdata:max_bounds:%s:%s' % (cls.__name__, MapUpdate.current_cache_key())
|
2017-10-19 13:55:35 +02:00
|
|
|
result = cache.get(cache_key, None)
|
|
|
|
if result is not None:
|
|
|
|
return result
|
2017-10-29 11:32:44 +01:00
|
|
|
result = cls.objects.all().aggregate(models.Min('left'), models.Min('bottom'),
|
|
|
|
models.Max('right'), models.Max('top'))
|
2018-11-16 00:52:13 +01:00
|
|
|
result = ((float(result['left__min'] or 0), float(result['bottom__min'] or 0)),
|
|
|
|
(float(result['right__max'] or 10), float(result['top__max'] or 10)))
|
2017-10-19 13:55:35 +02:00
|
|
|
cache.set(cache_key, result, 900)
|
|
|
|
return result
|
2017-05-26 21:25:54 +02:00
|
|
|
|
2017-06-11 14:43:14 +02:00
|
|
|
def _serialize(self, level=True, **kwargs):
|
2017-05-26 21:25:54 +02:00
|
|
|
result = super()._serialize(**kwargs)
|
|
|
|
result['bounds'] = self.bounds
|
|
|
|
return result
|
|
|
|
|
|
|
|
@property
|
|
|
|
def bounds(self):
|
|
|
|
# noinspection PyTypeChecker
|
2017-10-29 11:32:44 +01:00
|
|
|
return (float(self.left), float(self.bottom)), (float(self.right), float(self.top))
|