From 85d4d8166ec7faa0b711e4bebb7c8b0401e52c18 Mon Sep 17 00:00:00 2001 From: BelpHegoR17 Date: Sun, 7 Dec 2025 11:30:26 +0530 Subject: [PATCH 1/2] [filters] Improve invalid geometry handling in GeometryFilter #187 Implemented safer handling of invalid geometry input by: - validating geometry in a custom SafeGeometryField - catching GEOSException, GDALException, ValueError and TypeError in GeometryFilter.filter This prevents server error like: "Invalid geometry pointer returned from OGR_G_CreateGeometryFromJson" and ensures a clean 400 ValidationError response instead. Fixes #187 --- rest_framework_gis/filters.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/rest_framework_gis/filters.py b/rest_framework_gis/filters.py index 0bdb5d3b..0337953f 100644 --- a/rest_framework_gis/filters.py +++ b/rest_framework_gis/filters.py @@ -4,10 +4,12 @@ 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 +from rest_framework.exceptions import ParseError, ValidationError from rest_framework.filters import BaseFilterBackend from .tilenames import tile_edges @@ -91,15 +93,30 @@ def get_schema_operation_parameters(self, view): # backward compatibility 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) as e: + raise ValidationError(f"Invalid geometry value: {str(e)}") + class GeoFilterSet(django_filters.FilterSet): GEOFILTER_FOR_DBFIELD_DEFAULTS = { models.GeometryField: {"filterset_class": GeometryFilter}, From 6b9530db16538427f349e40607e510887712c8da Mon Sep 17 00:00:00 2001 From: BelpHegoR17 Date: Sun, 7 Dec 2025 14:26:17 +0530 Subject: [PATCH 2/2] [filters] Apply formatting fixes and unify error messages #187 -Added required blank lines before class definition -Unified error messages between SafeGeometryField and GeometryFilter -Removed trailing whitespaces Fixes #187 --- rest_framework_gis/filters.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/rest_framework_gis/filters.py b/rest_framework_gis/filters.py index 0337953f..2c423318 100644 --- a/rest_framework_gis/filters.py +++ b/rest_framework_gis/filters.py @@ -9,7 +9,7 @@ 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, ValidationError +from rest_framework.exceptions import ParseError from rest_framework.filters import BaseFilterBackend from .tilenames import tile_edges @@ -93,6 +93,7 @@ def get_schema_operation_parameters(self, view): # backward compatibility InBBOXFilter = InBBoxFilter + class SafeGeometryField(forms.GeometryField): """ GeometryField that converts GEOS/GDAL errors into ValidationError. @@ -104,19 +105,21 @@ def to_python(self, value): except (GEOSException, GDALException, ValueError, TypeError): raise forms.ValidationError("Invalid geometry value.") + class GeometryFilter(django_filters.Filter): 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) as e: - raise ValidationError(f"Invalid geometry value: {str(e)}") - + except (GEOSException, GDALException, ValueError, TypeError): + raise forms.ValidationError("Invalid geometry value.") + + class GeoFilterSet(django_filters.FilterSet): GEOFILTER_FOR_DBFIELD_DEFAULTS = { models.GeometryField: {"filterset_class": GeometryFilter},