fix locationredirects breaking querysets

This commit is contained in:
Laura Klünder 2024-12-04 12:42:03 +01:00
parent 07a3c5ffa9
commit 00ec22c334
4 changed files with 37 additions and 25 deletions

View file

@ -48,8 +48,9 @@ class LocationSlugManager(models.Manager):
if self.model != LocationSlug:
raise TypeError
qs = self.get_queryset()
qs = qs.select_related('redirect__target', *('redirect__target__'+model._meta.default_related_name
for model in get_submodels(Location) + [LocationRedirect]))
qs = qs.select_related('locationredirects__target',
*('locationredirects__target__'+model._meta.default_related_name
for model in get_submodels(Location) + [LocationRedirect]))
return qs
@ -108,15 +109,6 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model):
class Meta:
abstract = True
def serialize(self, detailed=True, **kwargs):
result = super().serialize(detailed=detailed, **kwargs)
if not detailed:
fields = ('id', 'type', 'slug', 'effective_slug', 'title', 'subtitle', 'icon', 'point', 'bounds',
'grid_square', 'locations', 'on_top_of', 'effective_label_settings', 'label_override',
'add_search', 'dynamic', 'locationtype', 'geometry')
result = {name: result[name] for name in fields if name in result}
return result
@property
def add_search(self):
return ' '.join((
@ -495,6 +487,7 @@ class DynamicLocation(CustomLocationProxyMixin, SpecificLocation, models.Model):
pass
def serialize_position(self, request=None):
# todo: make this pretty
custom_location = self.get_custom_location(request=request)
if custom_location is None:
return {
@ -505,7 +498,8 @@ class DynamicLocation(CustomLocationProxyMixin, SpecificLocation, models.Model):
'title': str(self.title),
'subtitle': '%s %s, %s' % (_('currently unavailable'), _('(moving)'), self.subtitle)
}
result = custom_location.serialize(simple_geometry=True)
from c3nav.mapdata.schemas.models import CustomLocationSchema
result = CustomLocationSchema.model_validate(custom_location).model_dump()
result.update({
'available': True,
'id': self.pk,
@ -586,6 +580,7 @@ class Position(CustomLocationProxyMixin, models.Model):
return result
def serialize_position(self, request=None):
# todo: make this pretty
custom_location = self.get_custom_location(request=request)
if custom_location is None:
return {
@ -596,7 +591,8 @@ class Position(CustomLocationProxyMixin, models.Model):
'title': self.name,
'subtitle': _('currently unavailable'),
}
result = custom_location.serialize(simple_geometry=True)
from c3nav.mapdata.schemas.models import CustomLocationSchema
result = CustomLocationSchema.model_validate(custom_location).model_dump()
result.update({
'available': True,
'id': 'p:%s' % self.secret,
@ -619,20 +615,22 @@ class Position(CustomLocationProxyMixin, models.Model):
def slug(self):
return 'p:%s' % self.secret
@property
def subtitle(self):
return _('Position')
@property
def icon(self):
return 'my_location'
@property
def effective_icon(self):
return self.icon
@property
def effective_slug(self):
return self.slug
def serialize(self, *args, **kwargs):
return {
'dynamic': True,
'id': 'p:%s' % self.secret,
'slug': 'p:%s' % self.secret,
'icon': 'my_location',
'title': self.name,
'subtitle': _('Position'),
}
def details_display(self, **kwargs):
return {
'id': self.pk,

View file

@ -1,3 +1,4 @@
from contextlib import suppress
from typing import Annotated, ClassVar, Literal, Optional, Union, Any
from django.db.models import Model
@ -545,6 +546,14 @@ class TrackablePositionSchema(BaseSchema):
example="Near Bällebad"
)
@classmethod
def get_overrides(cls, value) -> dict:
from c3nav.mapdata.models.locations import Position
value: Position
return {
"id": value.slug,
}
class LocationTypeSchema(BaseSchema):
locationtype: str = APIField(title="location type",
@ -695,6 +704,8 @@ class SlimDynamicLocationLocationSchema(SlimLocationMixin, FullDynamicLocationLo
def get_locationtype(v: Any):
if isinstance(v, Model):
return v._meta.model_name
with suppress(AttributeError):
return v.locationtype
return v["locationtype"]

View file

@ -40,7 +40,7 @@ def locations_for_request(request) -> Mapping[int, LocationSlug]:
conditions = []
for model in get_submodels(Location):
related_name = model._meta.default_related_name
for prefix in ('', 'redirect__target__'):
for prefix in ('', 'locationredirects__target__'):
condition = Q(**{prefix + related_name + '__isnull': False})
# noinspection PyUnresolvedReferences
condition &= model.q_for_request(request, prefix=prefix + related_name + '__')
@ -52,7 +52,7 @@ def locations_for_request(request) -> Mapping[int, LocationSlug]:
)
locations = locations.filter(reduce(operator.or_, conditions))
locations = locations.select_related('redirect', 'locationgroups__category')
locations = locations.select_related('locationredirects', 'locationgroups__category')
# prefetch locationgroups
base_qs = LocationGroup.qs_for_request(request).select_related('category', 'label_settings')
@ -275,6 +275,8 @@ def get_custom_location_for_request(slug: str, request):
@dataclass
class CustomLocation:
new_serialize: ClassVar = True
locationtype: ClassVar = "customlocation"
can_search = True

View file

@ -534,6 +534,7 @@ CustomLocationDescription = namedtuple('CustomLocationDescription', ('space', 'a
'areas', 'near_area', 'near_poi', 'nearby'))
# todo: make generic
class BaseRouterProxy:
def __init__(self, src):
self.src = src