diff --git a/rest_framework_gis/filters.py b/rest_framework_gis/filters.py index 0bdb5d3b..2c423318 100644 --- a/rest_framework_gis/filters.py +++ b/rest_framework_gis/filters.py @@ -4,7 +4,9 @@ from django.contrib.gis.db import models from django.contrib.gis.db.models.fields import BaseSpatialField from django.contrib.gis.db.models.functions import GeometryDistance +from django.contrib.gis.gdal.error import GDALException from django.contrib.gis.geos import Point, Polygon +from django.contrib.gis.geos.error import GEOSException from django.core.exceptions import ImproperlyConfigured from django.db.models import Q from rest_framework.exceptions import ParseError @@ -92,13 +94,31 @@ def get_schema_operation_parameters(self, view): InBBOXFilter = InBBoxFilter +class SafeGeometryField(forms.GeometryField): + """ + GeometryField that converts GEOS/GDAL errors into ValidationError. + """ + + def to_python(self, value): + try: + return super().to_python(value) + except (GEOSException, GDALException, ValueError, TypeError): + raise forms.ValidationError("Invalid geometry value.") + + class GeometryFilter(django_filters.Filter): - field_class = forms.GeometryField + field_class = SafeGeometryField def __init__(self, *args, **kwargs): kwargs.setdefault("widget", forms.TextInput) super().__init__(*args, **kwargs) + def filter(self, qs, value): + try: + return super().filter(qs, value) + except (GEOSException, GDALException, ValueError, TypeError): + raise forms.ValidationError("Invalid geometry value.") + class GeoFilterSet(django_filters.FilterSet): GEOFILTER_FOR_DBFIELD_DEFAULTS = {