예제 #1
0
def register_signals():
    from c3nav.mapdata.models.geometry.base import GeometryMixin
    for model in get_submodels(GeometryMixin):
        post_delete.connect(geometry_deleted, sender=model)

    from c3nav.mapdata.models.locations import SpecificLocation
    for model in get_submodels(SpecificLocation):
        m2m_changed.connect(locationgroup_changed, sender=model.groups.through)
예제 #2
0
def register_signals():
    from c3nav.mapdata.models.geometry.base import GeometryMixin
    for model in get_submodels(GeometryMixin):
        post_delete.connect(geometry_deleted, sender=model)

    from c3nav.mapdata.models.locations import SpecificLocation
    for model in get_submodels(SpecificLocation):
        m2m_changed.connect(locationgroup_changed, sender=model.groups.through)
예제 #3
0
파일: locations.py 프로젝트: imkeines/c3nav
 def select_related_target(self):
     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]))
     return qs
예제 #4
0
 def get_queryset(self):
     """
     make sure that the database does not return objects that have been deleted in this changeset
     """
     qs = self._wrap_queryset(self._obj.model.objects.all())
     return qs.exclude(pk__in=tuple(chain(*(self._changeset.deleted_existing.get(submodel, ())
                                            for submodel in get_submodels(self._obj.model)))))
예제 #5
0
 def get_queryset(self):
     result = super().get_queryset()
     if self.model == LocationSlug:
         result = result.select_related(
             *(model._meta.default_related_name
               for model in get_submodels(Location) + [LocationRedirect]))
     return result
예제 #6
0
파일: changeset.py 프로젝트: JefferyQ/c3nav
    def get_changed_object(self, obj) -> ChangedObject:
        if isinstance(obj, ModelInstanceWrapper):
            obj = obj._obj
        model = obj.__class__
        pk = obj.pk
        if pk is None:
            return ChangedObject(changeset=self, model_class=model)

        self.fill_changes_cache()

        objects = tuple(
            obj
            for obj in ((submodel,
                         self.changed_objects.get(submodel, {}).get(pk, None))
                        for submodel in get_submodels(model))
            if obj[1] is not None)
        if len(objects) > 1:
            raise model.MultipleObjectsReturned
        if objects:
            return objects[0][1]

        if is_created_pk(pk):
            raise model.DoesNotExist

        return ChangedObject(changeset=self,
                             model_class=model,
                             existing_object_pk=pk)
예제 #7
0
 def get_queryset(self):
     """
     make sure that the database does not return objects that have been deleted in this changeset
     """
     qs = self._wrap_queryset(self._obj.model.objects.all())
     return qs.exclude(pk__in=tuple(chain(*(self._changeset.deleted_existing.get(submodel, ())
                                            for submodel in get_submodels(self._obj.model)))))
예제 #8
0
 def register_changed_geometries(self, do_query=True):
     from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
     for model in get_submodels(SpecificLocation):
         query = getattr(self, model._meta.default_related_name).all()
         if do_query:
             if issubclass(model, SpaceGeometryMixin):
                 query = query.select_related('space')
         for obj in query:
             obj.register_change(force=True)
예제 #9
0
 def register_changed_geometries(self, do_query=True):
     from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
     for model in get_submodels(SpecificLocation):
         query = getattr(self, model._meta.default_related_name).all()
         if do_query:
             if issubclass(model, SpaceGeometryMixin):
                 query = query.select_related('space')
         for obj in query:
             obj.register_change(force=True)
예제 #10
0
파일: locations.py 프로젝트: imkeines/c3nav
    def register_changed_geometries(self):
        from c3nav.mapdata.models.geometry.space import SpaceGeometryMixin
        query = self.groups.all()
        for model in get_submodels(SpecificLocation):
            related_name = model._meta.default_related_name
            subquery = model.objects.all()
            if issubclass(model, SpaceGeometryMixin):
                subquery = subquery.select_related('space')
            query.prefetch_related(Prefetch('groups__'+related_name, subquery))

        for group in query:
            group.register_changed_geometries(do_query=False)
예제 #11
0
파일: locations.py 프로젝트: imkeines/c3nav
 def get_queryset(self):
     result = super().get_queryset()
     if self.model == LocationSlug:
         for model in get_submodels(Location) + [LocationRedirect]:
             result = result.select_related(model._meta.default_related_name)
             try:
                 model._meta.get_field('space')
             except FieldDoesNotExist:
                 pass
             else:
                 result = result.select_related(model._meta.default_related_name+'__space')
     return result
예제 #12
0
 def handle(self, *args, **options):
     with transaction.atomic():
         for model in get_submodels(GeometryMixin):
             for instance in model.objects.all():
                 old_geom = instance.geometry.wrapped_geojson
                 if instance.geometry.is_empty:
                     print('Deleted %s' % instance)
                     instance.delete()
                     continue
                 instance.save()
                 instance.refresh_from_db()
                 if instance.geometry.wrapped_geojson != old_geom:
                     print('Fixed %s' % instance)
예제 #13
0
 def qs_for_request(cls, request):
     if request.user_permissions.review_all_reports:
         return cls.objects.all()
     elif request.user.is_authenticated:
         location_ids = set()
         review_group_ids = request.user_permissions.review_group_ids
         for model in get_submodels(SpecificLocation):
             location_ids.update(set(
                 model.objects.filter(groups__in=review_group_ids).values_list('pk', flat=True)
             ))
         return cls.objects.filter(
             Q(author=request.user) |
             Q(location_id__in=location_ids) |
             Q(created_groups__in=review_group_ids)
         )
     else:
         return cls.objects.none()
예제 #14
0
    def get_changed_object(self, obj) -> ChangedObject:
        if isinstance(obj, ModelInstanceWrapper):
            obj = obj._obj
        model = obj.__class__
        pk = obj.pk
        if pk is None:
            return ChangedObject(changeset=self, model_class=model)

        self.fill_changes_cache()

        objects = tuple(obj for obj in ((submodel, self.changed_objects.get(submodel, {}).get(pk, None))
                                        for submodel in get_submodels(model)) if obj[1] is not None)
        if len(objects) > 1:
            raise model.MultipleObjectsReturned
        if objects:
            return objects[0][1]

        if is_created_pk(pk):
            raise model.DoesNotExist

        return ChangedObject(changeset=self, model_class=model, existing_object_pk=pk)
예제 #15
0
 def get_child(self, instance=None):
     for model in get_submodels(Location) + [LocationRedirect]:
         with suppress(AttributeError):
             return getattr(instance or self,
                            model._meta.default_related_name)
     return None
예제 #16
0
 def _submodels(self):
     """
     Get non-abstract submodels for this model including the model itself.
     """
     return get_submodels(self._obj)
예제 #17
0
파일: api.py 프로젝트: nomoketo/c3nav-new
 def types(self, request):
     return MapdataViewSet.list_types(get_submodels(Location), geomtype=False)
예제 #18
0
파일: api.py 프로젝트: nomoketo/c3nav-new
 def geometrytypes(self, request):
     return self.list_types(get_submodels(SpaceGeometryMixin))
예제 #19
0
파일: api.py 프로젝트: exmatrikulator/c3nav
 def types(self, request):
     return MapdataViewSet.list_types(get_submodels(Location),
                                      geomtype=False)
예제 #20
0
파일: api.py 프로젝트: exmatrikulator/c3nav
 def geometrytypes(self, request):
     return self.list_types(get_submodels(SpaceGeometryMixin))
예제 #21
0
 def _submodels(self):
     """
     Get non-abstract submodels for this model including the model itself.
     """
     return get_submodels(self._obj)
예제 #22
0
 def get_child(self, instance=None):
     for model in get_submodels(Location)+[LocationRedirect]:
         with suppress(AttributeError):
             return getattr(instance or self, model._meta.default_related_name)
     return None
예제 #23
0
def locations_for_request(request) -> Mapping[int, LocationSlug]:
    cache_key = 'mapdata:locations:%s' % AccessPermission.cache_key_for_request(request)
    locations = proxied_cache.get(cache_key, None)
    if locations is not None:
        return locations

    locations = LocationSlug.objects.all().order_by('id')

    conditions = []
    for model in get_submodels(Location):
        related_name = model._meta.default_related_name
        condition = Q(**{related_name + '__isnull': False})
        # noinspection PyUnresolvedReferences
        condition &= model.q_for_request(request, prefix=related_name + '__')
        conditions.append(condition)
    locations = locations.filter(reduce(operator.or_, conditions))
    locations.select_related('redirect', 'locationgroups__category')

    # prefetch locationgroups
    base_qs = LocationGroup.qs_for_request(request).select_related('category')
    for model in get_submodels(SpecificLocation):
        locations = locations.prefetch_related(Prefetch(model._meta.default_related_name + '__groups',
                                                        queryset=base_qs))

    locations = {obj.pk: obj.get_child() for obj in locations}

    # add locations to groups
    locationgroups = {pk: obj for pk, obj in locations.items() if isinstance(obj, LocationGroup)}
    for group in locationgroups.values():
        group.locations = []
    for obj in locations.values():
        if not isinstance(obj, SpecificLocation):
            continue
        for group in obj.groups.all():
            group = locationgroups.get(group.pk, None)
            if group is not None:
                group.locations.append(obj)

    # add levels to spaces
    remove_pks = set()
    levels = {pk: obj for pk, obj in locations.items() if isinstance(obj, Level)}
    for pk, obj in locations.items():
        if isinstance(obj, LevelGeometryMixin):
            level = levels.get(obj.level_id, None)
            if level is None:
                remove_pks.add(pk)
                continue
            obj._level_cache = level

    # hide spaces on hidden levels
    for pk in remove_pks:
        locations.pop(pk)

    # add spaces to areas and POIs
    remove_pks = set()
    spaces = {pk: obj for pk, obj in locations.items() if isinstance(obj, Space)}
    for pk, obj in locations.items():
        if isinstance(obj, SpaceGeometryMixin):
            space = spaces.get(obj.space_id, None)
            if space is None:
                remove_pks.add(pk)
                continue
            obj._space_cache = space

    # hide locations on hidden spaces
    for pk in remove_pks:
        locations.pop(pk)

    # add targets to LocationRedirects
    levels = {pk: obj for pk, obj in locations.items() if isinstance(obj, Level)}
    for obj in locations.values():
        if isinstance(obj, LocationRedirect):
            obj._target_cache = locations.get(obj.target_id, None)

    # apply better space geometries
    for pk, geometry in get_better_space_geometries().items():
        if pk in locations:
            locations[pk].geometry = geometry

    # precache cached properties
    for obj in locations.values():
        # noinspection PyStatementEffect
        obj.subtitle, obj.order
        if isinstance(obj, GeometryMixin):
            # noinspection PyStatementEffect
            obj.point

    proxied_cache.set(cache_key, locations, 1800)

    return locations
예제 #24
0
def locations_for_request(request) -> Mapping[int, LocationSlug]:
    # todo this takes a long time because it's a lot of data, we might want to change that
    cache_key = 'mapdata:locations:%s' % AccessPermission.cache_key_for_request(
        request)
    locations = proxied_cache.get(cache_key, None)
    if locations is not None:
        return locations

    locations = LocationSlug.objects.all().order_by('id')

    conditions = []
    for model in get_submodels(Location):
        related_name = model._meta.default_related_name
        condition = Q(**{related_name + '__isnull': False})
        # noinspection PyUnresolvedReferences
        condition &= model.q_for_request(request, prefix=related_name + '__')
        conditions.append(condition)
        locations = locations.select_related(
            related_name + '__label_settings').prefetch_related(related_name +
                                                                '__redirects')
    locations = locations.filter(reduce(operator.or_, conditions))
    locations = locations.select_related('redirect',
                                         'locationgroups__category')

    # prefetch locationgroups
    base_qs = LocationGroup.qs_for_request(request).select_related(
        'category', 'label_settings')
    for model in get_submodels(SpecificLocation):
        locations = locations.prefetch_related(
            Prefetch(model._meta.default_related_name + '__groups',
                     queryset=base_qs))

    locations = {obj.pk: obj.get_child() for obj in locations}

    # add locations to groups
    locationgroups = {
        pk: obj
        for pk, obj in locations.items() if isinstance(obj, LocationGroup)
    }
    for group in locationgroups.values():
        group.locations = []
    for obj in locations.values():
        if not isinstance(obj, SpecificLocation):
            continue
        for group in obj.groups.all():
            group = locationgroups.get(group.pk, None)
            if group is not None:
                group.locations.append(obj)

    # add levels to spaces
    remove_pks = set()
    levels = {
        pk: obj
        for pk, obj in locations.items() if isinstance(obj, Level)
    }
    for pk, obj in locations.items():
        if isinstance(obj, LevelGeometryMixin):
            level = levels.get(obj.level_id, None)
            if level is None:
                remove_pks.add(pk)
                continue
            obj._level_cache = level

    # hide spaces on hidden levels
    for pk in remove_pks:
        locations.pop(pk)

    # add spaces to areas and POIs
    remove_pks = set()
    spaces = {
        pk: obj
        for pk, obj in locations.items() if isinstance(obj, Space)
    }
    for pk, obj in locations.items():
        if isinstance(obj, SpaceGeometryMixin):
            space = spaces.get(obj.space_id, None)
            if space is None:
                remove_pks.add(pk)
                continue
            obj._space_cache = space

    # hide locations on hidden spaces
    for pk in remove_pks:
        locations.pop(pk)

    # add targets to LocationRedirects
    levels = {
        pk: obj
        for pk, obj in locations.items() if isinstance(obj, Level)
    }
    for obj in locations.values():
        if isinstance(obj, LocationRedirect):
            obj._target_cache = locations.get(obj.target_id, None)

    # apply better space geometries
    for pk, geometry in get_better_space_geometries().items():
        if pk in locations:
            locations[pk].geometry = geometry

    # precache cached properties
    for obj in locations.values():
        # noinspection PyStatementEffect
        obj.subtitle, obj.order
        if isinstance(obj, GeometryMixin):
            # noinspection PyStatementEffect
            obj.point

    proxied_cache.set(cache_key, locations, 1800)

    return locations