Skip to content

GDALException raised when providing bad input to GeometryFilter #187

Open
@nattyg93

Description

@nattyg93

My setup it is something along the lines of this:

class Location(models.Model):
    point = models.PointField(geography=True)


class LocationFilterSet(filters.FilterSet):

    within = GeometryFilter(
        field_name="point", srid=4326, method="filter_within"
    )

    class Meta:
        model = Location
        fields = ["within"]

    def filter_within(self, qs, name, value):
        return qs.filter(**{f"{name}__dwithin": (value, Distance(1))})

class LocationViewSet(ModelViewSet):
    queryset = Location.objects.all()
    filter_backends = (django_filters.DjangoFilterBackend, )
    filter_class = LocationFilterSet

When I query the filter providing invalid input http://localhost:8000/api/locations/?within={"type":"Feature","I am not valid":"1,1,1"}

I get the following exception:

  return self.application(environ, start_response)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/wsgi.py", line 142, in __call__
  response = self.get_response(request)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 78, in get_response
  response = self._middleware_chain(request)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 36, in inner
  response = response_for_exception(request, exc)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
  response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
  return debug.technical_500_response(request, *exc_info)
File "/var/www/.venv/lib/python3.7/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
  six.reraise(exc_type, exc_value, tb)
File "/var/www/.venv/lib/python3.7/site-packages/six.py", line 692, in reraise
  raise value.with_traceback(tb)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
  response = get_response(request)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
  response = self.process_exception_by_middleware(e, request)
File "/var/www/.venv/lib/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
  response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/.venv/lib/python3.7/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
  return view_func(*args, **kwargs)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/viewsets.py", line 116, in view
  return self.dispatch(request, *args, **kwargs)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/views.py", line 495, in dispatch
  response = self.handle_exception(exc)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/views.py", line 455, in handle_exception
  self.raise_uncaught_exception(exc)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/views.py", line 492, in dispatch
  response = handler(request, *args, **kwargs)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/mixins.py", line 40, in list
  queryset = self.filter_queryset(self.get_queryset())
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework/generics.py", line 152, in filter_queryset
  queryset = backend().filter_queryset(self.request, queryset, self)
File "/var/www/.venv/lib/python3.7/site-packages/rest_framework_json_api/django_filters/backends.py", line 134, in filter_queryset
  return super(DjangoFilterBackend, self).filter_queryset(request, queryset, view)
File "/var/www/.venv/lib/python3.7/site-packages/django_filters/rest_framework/backends.py", line 94, in filter_queryset
  if not filterset.is_valid() and self.raise_exception:
File "/var/www/.venv/lib/python3.7/site-packages/django_filters/filterset.py", line 206, in is_valid
  return self.is_bound and self.form.is_valid()
File "/var/www/.venv/lib/python3.7/site-packages/django/forms/forms.py", line 185, in is_valid
  return self.is_bound and not self.errors
File "/var/www/.venv/lib/python3.7/site-packages/django/forms/forms.py", line 180, in errors
  self.full_clean()
File "/var/www/.venv/lib/python3.7/site-packages/django/forms/forms.py", line 381, in full_clean
  self._clean_fields()
File "/var/www/.venv/lib/python3.7/site-packages/django/forms/forms.py", line 399, in _clean_fields
  value = field.clean(value)
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/forms/fields.py", line 63, in clean
  geom = super().clean(value)
File "/var/www/.venv/lib/python3.7/site-packages/django/forms/fields.py", line 147, in clean
  value = self.to_python(value)
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/forms/fields.py", line 42, in to_python
  value = GEOSGeometry(value)
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/geos/geometry.py", line 705, in __init__
  ogr = gdal.OGRGeometry.from_json(geo_input)
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/gdal/geometries.py", line 161, in from_json
  return OGRGeometry(OGRGeometry._from_json(force_bytes(geom_input)))
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/gdal/geometries.py", line 143, in _from_json
  ptr = capi.from_json(geom_input)
File "/var/www/.venv/lib/python3.7/site-packages/django/contrib/gis/gdal/prototypes/errcheck.py", line 84, in check_geom
  raise GDALException('Invalid geometry pointer returned from "%s".' % func.__name__)
django.contrib.gis.gdal.error.GDALException: Invalid geometry pointer returned from "OGR_G_CreateGeometryFromJson".

I've kind of fixed the issue by using the code below. This doesn't seem like a hugely eloquent solution though.

from django.contrib.gis import forms
from rest_framework_gis.filters import GeometryFilter as BaseGeometryFilter

class GeometryField(forms.GeometryField):
    """Catch GDALException."""

    def to_python(self, value):
        """Catch GDALException."""
        try:
            return super().to_python(value)
        except GDALException as e:
            raise forms.ValidationError("Invalid geometry value.")


class GeometryFilter(BaseGeometryFilter):
    """Catch GDALException."""

    field_class = GeometryField

Is there something I'm missing? I've read through the docs and check the issues and I can't seem to find a better solution.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    To do (Python & Django)

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions