new serializer for locationgroup
This commit is contained in:
parent
db938414fb
commit
cc2020e7c3
10 changed files with 58 additions and 57 deletions
|
@ -64,7 +64,7 @@ class LevelGeometryMixin(GeometryMixin):
|
||||||
_('Level'),
|
_('Level'),
|
||||||
{
|
{
|
||||||
'id': self.level_id,
|
'id': self.level_id,
|
||||||
'slug': self.level.get_slug(),
|
'slug': self.level.effective_slug,
|
||||||
'title': self.level.title,
|
'title': self.level.title,
|
||||||
'can_search': self.level.can_search,
|
'can_search': self.level.can_search,
|
||||||
},
|
},
|
||||||
|
|
|
@ -93,7 +93,7 @@ class SpaceGeometryMixin(GeometryMixin):
|
||||||
_('Space'),
|
_('Space'),
|
||||||
{
|
{
|
||||||
'id': self.space_id,
|
'id': self.space_id,
|
||||||
'slug': self.space.get_slug(),
|
'slug': self.space.effective_slug,
|
||||||
'title': self.space.title,
|
'title': self.space.title,
|
||||||
'can_search': self.space.can_search,
|
'can_search': self.space.can_search,
|
||||||
},
|
},
|
||||||
|
|
|
@ -81,18 +81,20 @@ class LocationSlug(SerializableMixin, models.Model):
|
||||||
return getattr(self, model._meta.default_related_name)
|
return getattr(self, model._meta.default_related_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_slug(self):
|
@property
|
||||||
|
def effective_slug(self):
|
||||||
return self.slug
|
return self.slug
|
||||||
|
|
||||||
def _serialize(self, **kwargs):
|
def _serialize(self, **kwargs):
|
||||||
result = super()._serialize(**kwargs)
|
result = super()._serialize(**kwargs)
|
||||||
result["locationtype"] = self.__class__.__name__.lower()
|
result["locationtype"] = self.__class__.__name__.lower()
|
||||||
result['slug'] = self.get_slug()
|
result['slug'] = self.slug
|
||||||
|
result['effective_slug'] = self.effective_slug
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def details_display(self, **kwargs):
|
def details_display(self, **kwargs):
|
||||||
result = super().details_display(**kwargs)
|
result = super().details_display(**kwargs)
|
||||||
result['display'].insert(2, (_('Slug'), self.get_slug()))
|
result['display'].insert(2, (_('Slug'), self.effective_slug))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -116,9 +118,9 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model):
|
||||||
def serialize(self, detailed=True, **kwargs):
|
def serialize(self, detailed=True, **kwargs):
|
||||||
result = super().serialize(detailed=detailed, **kwargs)
|
result = super().serialize(detailed=detailed, **kwargs)
|
||||||
if not detailed:
|
if not detailed:
|
||||||
fields = ('id', 'type', 'slug', 'title', 'subtitle', 'icon', 'point', 'bounds', 'grid_square',
|
fields = ('id', 'type', 'slug', 'effective_slug', 'title', 'subtitle', 'icon', 'point', 'bounds',
|
||||||
'locations', 'on_top_of', 'effective_label_settings', 'label_override', 'add_search', 'dynamic',
|
'grid_square', 'locations', 'on_top_of', 'effective_label_settings', 'label_override',
|
||||||
'locationtype', 'geometry')
|
'add_search', 'dynamic', 'locationtype', 'geometry')
|
||||||
result = {name: result[name] for name in fields if name in result}
|
result = {name: result[name] for name in fields if name in result}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -144,7 +146,8 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model):
|
||||||
])
|
])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def get_slug(self):
|
@property
|
||||||
|
def effective_slug(self):
|
||||||
if self.slug is None:
|
if self.slug is None:
|
||||||
code = self.LOCATION_TYPE_CODES.get(self.__class__.__name__)
|
code = self.LOCATION_TYPE_CODES.get(self.__class__.__name__)
|
||||||
if code is not None:
|
if code is not None:
|
||||||
|
@ -244,7 +247,7 @@ class SpecificLocation(Location, models.Model):
|
||||||
category.title if category.single else category.title_plural,
|
category.title if category.single else category.title_plural,
|
||||||
tuple({
|
tuple({
|
||||||
'id': group.pk,
|
'id': group.pk,
|
||||||
'slug': group.get_slug(),
|
'slug': group.effective_slug,
|
||||||
'title': group.title,
|
'title': group.title,
|
||||||
'can_search': group.can_search,
|
'can_search': group.can_search,
|
||||||
} for group in sorted(groups, key=attrgetter('priority'), reverse=True))
|
} for group in sorted(groups, key=attrgetter('priority'), reverse=True))
|
||||||
|
@ -356,6 +359,8 @@ class LocationGroupManager(models.Manager):
|
||||||
|
|
||||||
|
|
||||||
class LocationGroup(Location, models.Model):
|
class LocationGroup(Location, models.Model):
|
||||||
|
new_serialize = True
|
||||||
|
|
||||||
class CanReportMissing(models.TextChoices):
|
class CanReportMissing(models.TextChoices):
|
||||||
DONT_OFFER = "dont_offer", _("don't offer")
|
DONT_OFFER = "dont_offer", _("don't offer")
|
||||||
REJECT = "reject", _("offer in first step, then reject")
|
REJECT = "reject", _("offer in first step, then reject")
|
||||||
|
@ -692,7 +697,8 @@ class Position(CustomLocationProxyMixin, models.Model):
|
||||||
def slug(self):
|
def slug(self):
|
||||||
return 'p:%s' % self.secret
|
return 'p:%s' % self.secret
|
||||||
|
|
||||||
def get_slug(self):
|
@property
|
||||||
|
def effective_slug(self):
|
||||||
return self.slug
|
return self.slug
|
||||||
|
|
||||||
def serialize(self, *args, **kwargs):
|
def serialize(self, *args, **kwargs):
|
||||||
|
|
|
@ -41,11 +41,15 @@ class DjangoModelSchema(BaseSchema):
|
||||||
|
|
||||||
|
|
||||||
class LocationSlugSchema(BaseSchema):
|
class LocationSlugSchema(BaseSchema):
|
||||||
slug: NonEmptyStr = APIField(
|
slug: Optional[NonEmptyStr] = APIField(
|
||||||
title="location slug",
|
title="location slug",
|
||||||
description="a slug is a unique way to refer to a location. while locations have a shared ID space, slugs"
|
description="a slug is a unique way to refer to a location. while locations have a shared ID space, slugs"
|
||||||
"are meants to be human-readable and easy to remember.\n\n"
|
"are meants to be human-readable and easy to remember.",
|
||||||
"if a location doesn't have a slug defined, this field holds a slug generated from the "
|
example="entrance",
|
||||||
|
)
|
||||||
|
effective_slug: NonEmptyStr = APIField(
|
||||||
|
title="effective location slug",
|
||||||
|
description="if a location doesn't have a slug defined, this field holds a slug generated from the "
|
||||||
"location type and ID, which will work even if a human-readable slug is defined later.\n\n"
|
"location type and ID, which will work even if a human-readable slug is defined later.\n\n"
|
||||||
"even dynamic locations like coordinates have an (auto-generated) slug.",
|
"even dynamic locations like coordinates have an (auto-generated) slug.",
|
||||||
example="entrance",
|
example="entrance",
|
||||||
|
|
|
@ -222,16 +222,7 @@ class LocationGroupSchema(LocationSchema, DjangoModelSchema):
|
||||||
)
|
)
|
||||||
priority: int = APIField() # todo: ???
|
priority: int = APIField() # todo: ???
|
||||||
hierarchy: int = APIField() # todo: ???
|
hierarchy: int = APIField() # todo: ???
|
||||||
label_settings: Union[
|
label_settings: Optional[PositiveInt] = APIField(
|
||||||
Annotated[LabelSettingsSchema, APIField(
|
|
||||||
title="label settings",
|
|
||||||
description="label settings to use for gruop members that don't have their own set",
|
|
||||||
)],
|
|
||||||
Annotated[None, APIField(
|
|
||||||
title="null",
|
|
||||||
description="no label settings set"
|
|
||||||
)],
|
|
||||||
] = APIField(
|
|
||||||
default=None,
|
default=None,
|
||||||
title="label settings",
|
title="label settings",
|
||||||
description=(
|
description=(
|
||||||
|
|
18
src/c3nav/mapdata/utils/cache/stats.py
vendored
18
src/c3nav/mapdata/utils/cache/stats.py
vendored
|
@ -90,7 +90,7 @@ def convert_locate(data):
|
||||||
for measurement in BeaconMeasurement.objects.all().select_related('space', 'space__level'):
|
for measurement in BeaconMeasurement.objects.all().select_related('space', 'space__level'):
|
||||||
pos = CustomLocation(measurement.space.level, measurement.geometry.x, measurement.geometry.y,
|
pos = CustomLocation(measurement.space.level, measurement.geometry.x, measurement.geometry.y,
|
||||||
permissions=set())
|
permissions=set())
|
||||||
space_slug = measurement.space.get_slug()
|
space_slug = measurement.space.effective_slug
|
||||||
level_label = measurement.space.level.short_label
|
level_label = measurement.space.level.short_label
|
||||||
grid_square = pos.grid_square if grid.enabled else None
|
grid_square = pos.grid_square if grid.enabled else None
|
||||||
measurement_lookup[pos.pk] = (measurement.pk, grid_square, space_slug, level_label)
|
measurement_lookup[pos.pk] = (measurement.pk, grid_square, space_slug, level_label)
|
||||||
|
@ -143,23 +143,23 @@ def convert_location(data):
|
||||||
location = location.get_child()
|
location = location.get_child()
|
||||||
if isinstance(location, LocationRedirect):
|
if isinstance(location, LocationRedirect):
|
||||||
continue
|
continue
|
||||||
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(), {})[location.get_slug()] = 0
|
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(), {})[location.effective_slug] = 0
|
||||||
location_slugs[location.pk] = location.get_slug()
|
location_slugs[location.pk] = location.effective_slug
|
||||||
if isinstance(location, Level):
|
if isinstance(location, Level):
|
||||||
result['locations']['by_level'][location.short_label] = 0
|
result['locations']['by_level'][location.short_label] = 0
|
||||||
result['coordinates']['by_level'][location.short_label] = 0
|
result['coordinates']['by_level'][location.short_label] = 0
|
||||||
level_labels[location.pk] = location.short_label
|
level_labels[location.pk] = location.short_label
|
||||||
if isinstance(location, Space):
|
if isinstance(location, Space):
|
||||||
result['locations']['by_space'][location.get_slug()] = 0
|
result['locations']['by_space'][location.effective_slug] = 0
|
||||||
result['coordinates']['by_space'][location.get_slug()] = 0
|
result['coordinates']['by_space'][location.effective_slug] = 0
|
||||||
if isinstance(location, Area):
|
if isinstance(location, Area):
|
||||||
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
||||||
result['coordinates']['by_area'][location.get_slug()] = 0
|
result['coordinates']['by_area'][location.effective_slug] = 0
|
||||||
if isinstance(location, POI):
|
if isinstance(location, POI):
|
||||||
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
if getattr(location, 'can_search', False) or getattr(location, 'can_describe', False):
|
||||||
result['coordinates']['by_poi'][location.get_slug()] = 0
|
result['coordinates']['by_poi'][location.effective_slug] = 0
|
||||||
if isinstance(location, LocationGroup):
|
if isinstance(location, LocationGroup):
|
||||||
result['locations']['by_group'][location.get_slug()] = 0
|
result['locations']['by_group'][location.effective_slug] = 0
|
||||||
|
|
||||||
for name, value in data:
|
for name, value in data:
|
||||||
if name[0] != 'pk' or name[0] == 'c:anywhere':
|
if name[0] != 'pk' or name[0] == 'c:anywhere':
|
||||||
|
@ -187,7 +187,7 @@ def convert_location(data):
|
||||||
result['locations']['total'] += value
|
result['locations']['total'] += value
|
||||||
location = getattr(location, 'target', location)
|
location = getattr(location, 'target', location)
|
||||||
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(),
|
result['locations']['by_type'].setdefault(location.__class__.__name__.lower(),
|
||||||
{})[location.get_slug()] += value
|
{})[location.effective_slug] += value
|
||||||
if hasattr(location, 'space_id'):
|
if hasattr(location, 'space_id'):
|
||||||
result['locations']['by_space'][location_slugs[location.space_id]] += value
|
result['locations']['by_space'][location_slugs[location.space_id]] += value
|
||||||
if hasattr(location, 'level_id'):
|
if hasattr(location, 'level_id'):
|
||||||
|
|
|
@ -342,32 +342,32 @@ class CustomLocation:
|
||||||
(_('Slug'), self.pk),
|
(_('Slug'), self.pk),
|
||||||
(_('Level'), {
|
(_('Level'), {
|
||||||
'id': self.level.pk,
|
'id': self.level.pk,
|
||||||
'slug': self.level.get_slug(),
|
'slug': self.level.effective_slug,
|
||||||
'title': self.level.title,
|
'title': self.level.title,
|
||||||
'can_search': self.level.can_search,
|
'can_search': self.level.can_search,
|
||||||
}),
|
}),
|
||||||
(_('Space'), {
|
(_('Space'), {
|
||||||
'id': self.space.pk,
|
'id': self.space.pk,
|
||||||
'slug': self.space.get_slug(),
|
'slug': self.space.effective_slug,
|
||||||
'title': self.space.title,
|
'title': self.space.title,
|
||||||
'can_search': self.space.can_search,
|
'can_search': self.space.can_search,
|
||||||
} if self.space else None),
|
} if self.space else None),
|
||||||
(_('Areas'), tuple({
|
(_('Areas'), tuple({
|
||||||
'id': area.pk,
|
'id': area.pk,
|
||||||
'slug': area.get_slug(),
|
'slug': area.effective_slug,
|
||||||
'title': area.title,
|
'title': area.title,
|
||||||
'can_search': area.can_search,
|
'can_search': area.can_search,
|
||||||
} for area in self.areas)),
|
} for area in self.areas)),
|
||||||
(_('Grid Square'), self.grid_square or None),
|
(_('Grid Square'), self.grid_square or None),
|
||||||
(_('Near Area'), {
|
(_('Near Area'), {
|
||||||
'id': self.near_area.pk,
|
'id': self.near_area.pk,
|
||||||
'slug': self.near_area.get_slug(),
|
'slug': self.near_area.effective_slug,
|
||||||
'title': self.near_area.title,
|
'title': self.near_area.title,
|
||||||
'can_search': self.near_area.can_search,
|
'can_search': self.near_area.can_search,
|
||||||
} if self.near_area else None),
|
} if self.near_area else None),
|
||||||
(_('Near POI'), {
|
(_('Near POI'), {
|
||||||
'id': self.near_poi.pk,
|
'id': self.near_poi.pk,
|
||||||
'slug': self.near_poi.get_slug(),
|
'slug': self.near_poi.effective_slug,
|
||||||
'title': self.near_poi.title,
|
'title': self.near_poi.title,
|
||||||
'can_search': self.near_poi.can_search,
|
'can_search': self.near_poi.can_search,
|
||||||
} if self.near_poi else None),
|
} if self.near_poi else None),
|
||||||
|
@ -459,7 +459,8 @@ class CustomLocation:
|
||||||
def get_icon(self):
|
def get_icon(self):
|
||||||
return self.icon
|
return self.icon
|
||||||
|
|
||||||
def get_slug(self):
|
@property
|
||||||
|
def effective_slug(self):
|
||||||
return self.pk
|
return self.pk
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
|
|
@ -150,7 +150,7 @@ def preview_location(request, slug):
|
||||||
if location is None:
|
if location is None:
|
||||||
raise Http404
|
raise Http404
|
||||||
|
|
||||||
slug = location.get_slug()
|
slug = location.effective_slug
|
||||||
|
|
||||||
if isinstance(location, CustomLocation):
|
if isinstance(location, CustomLocation):
|
||||||
geometries = [Point(location.x, location.y)]
|
geometries = [Point(location.x, location.y)]
|
||||||
|
|
|
@ -169,7 +169,7 @@ c3nav = {
|
||||||
location.elem = c3nav._build_location_html(location);
|
location.elem = c3nav._build_location_html(location);
|
||||||
location.title_words = location.title.toLowerCase().split(/\s+/);
|
location.title_words = location.title.toLowerCase().split(/\s+/);
|
||||||
location.subtitle_words = location.subtitle.toLowerCase().split(/\s+/);
|
location.subtitle_words = location.subtitle.toLowerCase().split(/\s+/);
|
||||||
location.match = ' ' + location.title_words.join(' ') + ' ' + location.subtitle_words.join(' ') + ' ' + location.slug + ' ' + location.add_search.toLowerCase();
|
location.match = ' ' + location.title_words.join(' ') + ' ' + location.subtitle_words.join(' ') + ' ' + location.effective_slug + ' ' + location.add_search.toLowerCase();
|
||||||
locations.push(location);
|
locations.push(location);
|
||||||
locations_by_id[location.id] = location;
|
locations_by_id[location.id] = location;
|
||||||
if (location.point && location.label_settings) {
|
if (location.point && location.label_settings) {
|
||||||
|
@ -464,7 +464,7 @@ c3nav = {
|
||||||
for (var j = 0; j < sublocations.length; j++) {
|
for (var j = 0; j < sublocations.length; j++) {
|
||||||
loc = sublocations[j];
|
loc = sublocations[j];
|
||||||
if (loc.can_search) {
|
if (loc.can_search) {
|
||||||
loclist.append($('<a>').attr('href', '/l/' + loc.slug + '/details/').attr('data-id', loc.id).click(function (e) {
|
loclist.append($('<a>').attr('href', '/l/' + loc.effective_slug + '/details/').attr('data-id', loc.id).click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
c3nav._locationinput_set($('#destination-input'), c3nav.locations_by_id[parseInt($(this).attr('data-id'))]);
|
c3nav._locationinput_set($('#destination-input'), c3nav.locations_by_id[parseInt($(this).attr('data-id'))]);
|
||||||
c3nav.update_state(false, false, true);
|
c3nav.update_state(false, false, true);
|
||||||
|
@ -736,12 +736,12 @@ c3nav = {
|
||||||
var url = embed ? '/embed' : '';
|
var url = embed ? '/embed' : '';
|
||||||
if (state.routing) {
|
if (state.routing) {
|
||||||
if (state.origin) {
|
if (state.origin) {
|
||||||
url += (state.destination) ? '/r/' + state.origin.slug + '/' + state.destination.slug + '/' : '/o/' + state.origin.slug + '/';
|
url += (state.destination) ? '/r/' + state.origin.effective_slug + '/' + state.destination.effective_slug + '/' : '/o/' + state.origin.effective_slug + '/';
|
||||||
} else {
|
} else {
|
||||||
url += (state.destination) ? '/d/' + state.destination.slug + '/' : '/r/';
|
url += (state.destination) ? '/d/' + state.destination.effective_slug + '/' : '/r/';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
url += state.destination ? ('/l/' + state.destination.slug + '/') : '/';
|
url += state.destination ? ('/l/' + state.destination.effective_slug + '/') : '/';
|
||||||
}
|
}
|
||||||
if (state.details && (url.startsWith('/l/') || url.startsWith('/r/'))) {
|
if (state.details && (url.startsWith('/l/') || url.startsWith('/r/'))) {
|
||||||
url += 'details/'
|
url += 'details/'
|
||||||
|
@ -900,9 +900,8 @@ c3nav = {
|
||||||
_buttons_share_click: function (location) {
|
_buttons_share_click: function (location) {
|
||||||
var url = c3nav._get_share_url(false, location);
|
var url = c3nav._get_share_url(false, location);
|
||||||
if (navigator.share) {
|
if (navigator.share) {
|
||||||
var title
|
var title, subtitle;
|
||||||
, subtitle;
|
if (location.effective_slug) {
|
||||||
if (location.slug) {
|
|
||||||
title = location.title;
|
title = location.title;
|
||||||
subtitle = location.subtitle;
|
subtitle = location.subtitle;
|
||||||
} else {
|
} else {
|
||||||
|
@ -923,8 +922,8 @@ c3nav = {
|
||||||
},
|
},
|
||||||
_get_share_url: function (with_position, location) {
|
_get_share_url: function (with_position, location) {
|
||||||
var url, state = $.extend({}, c3nav.state);
|
var url, state = $.extend({}, c3nav.state);
|
||||||
if (location.slug) {
|
if (location.effective_slug) {
|
||||||
url = '/l/' + location.slug + '/';
|
url = '/l/' + location.effective_slug + '/';
|
||||||
} else {
|
} else {
|
||||||
if (!with_position) {
|
if (!with_position) {
|
||||||
state.center = null;
|
state.center = null;
|
||||||
|
|
|
@ -150,24 +150,24 @@ def map_index(request, mode=None, slug=None, slug2=None, details=None, options=N
|
||||||
metadata = {
|
metadata = {
|
||||||
'title': _('Route from %s to %s') % (origin.title, destination.title),
|
'title': _('Route from %s to %s') % (origin.title, destination.title),
|
||||||
'preview_img_url': request.build_absolute_uri(reverse('mapdata.preview.route', kwargs={
|
'preview_img_url': request.build_absolute_uri(reverse('mapdata.preview.route', kwargs={
|
||||||
'slug': origin.get_slug(),
|
'slug': origin.effective_slug,
|
||||||
'slug2': destination.get_slug(),
|
'slug2': destination.effective_slug,
|
||||||
})),
|
})),
|
||||||
'canonical_url': request.build_absolute_uri(reverse('site.index', kwargs={
|
'canonical_url': request.build_absolute_uri(reverse('site.index', kwargs={
|
||||||
'mode': 'r',
|
'mode': 'r',
|
||||||
'slug': origin.get_slug(),
|
'slug': origin.effective_slug,
|
||||||
'slug2': destination.get_slug(),
|
'slug2': destination.effective_slug,
|
||||||
'details': False,
|
'details': False,
|
||||||
'options': False,
|
'options': False,
|
||||||
})),
|
})),
|
||||||
}
|
}
|
||||||
elif destination is not None or origin is not None:
|
elif destination is not None or origin is not None:
|
||||||
if destination is not None:
|
if destination is not None:
|
||||||
loc_slug = destination.get_slug()
|
loc_slug = destination.effective_slug
|
||||||
title = destination.title
|
title = destination.title
|
||||||
subtitle = destination.subtitle if hasattr(destination, 'subtitle') else None
|
subtitle = destination.subtitle if hasattr(destination, 'subtitle') else None
|
||||||
else:
|
else:
|
||||||
loc_slug = origin.get_slug()
|
loc_slug = origin.effective_slug
|
||||||
title = origin.title
|
title = origin.title
|
||||||
subtitle = origin.subtitle if hasattr(origin, 'subtitle') else None
|
subtitle = origin.subtitle if hasattr(origin, 'subtitle') else None
|
||||||
metadata = {
|
metadata = {
|
||||||
|
@ -579,7 +579,7 @@ def report_missing_choose(request, coordinates):
|
||||||
'locations': [
|
'locations': [
|
||||||
{
|
{
|
||||||
"url": reverse('site.report_create',
|
"url": reverse('site.report_create',
|
||||||
kwargs={"coordinates": coordinates, "group": group.get_slug()}),
|
kwargs={"coordinates": coordinates, "group": group.effective_slug}),
|
||||||
"location": group,
|
"location": group,
|
||||||
"replace_subtitle": group.description
|
"replace_subtitle": group.description
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue