|
4 | 4 | from django.contrib.gis.db import models |
5 | 5 | from django.contrib.gis.db.models.fields import BaseSpatialField |
6 | 6 | from django.contrib.gis.db.models.functions import GeometryDistance |
| 7 | +from django.contrib.gis.gdal.error import GDALException |
7 | 8 | from django.contrib.gis.geos import Point, Polygon |
| 9 | +from django.contrib.gis.geos.error import GEOSException |
8 | 10 | from django.core.exceptions import ImproperlyConfigured |
9 | 11 | from django.db.models import Q |
10 | | -from rest_framework.exceptions import ParseError |
| 12 | +from rest_framework.exceptions import ParseError, ValidationError |
11 | 13 | from rest_framework.filters import BaseFilterBackend |
12 | 14 |
|
13 | 15 | from .tilenames import tile_edges |
@@ -91,15 +93,30 @@ def get_schema_operation_parameters(self, view): |
91 | 93 | # backward compatibility |
92 | 94 | InBBOXFilter = InBBoxFilter |
93 | 95 |
|
| 96 | +class SafeGeometryField(forms.GeometryField): |
| 97 | + """ |
| 98 | + GeometryField that converts GEOS/GDAL errors into ValidationError. |
| 99 | + """ |
| 100 | + |
| 101 | + def to_python(self, value): |
| 102 | + try: |
| 103 | + return super().to_python(value) |
| 104 | + except (GEOSException, GDALException, ValueError, TypeError): |
| 105 | + raise forms.ValidationError("Invalid geometry value.") |
94 | 106 |
|
95 | 107 | class GeometryFilter(django_filters.Filter): |
96 | | - field_class = forms.GeometryField |
| 108 | + field_class = SafeGeometryField |
97 | 109 |
|
98 | 110 | def __init__(self, *args, **kwargs): |
99 | 111 | kwargs.setdefault("widget", forms.TextInput) |
100 | 112 | super().__init__(*args, **kwargs) |
101 | | - |
102 | | - |
| 113 | + |
| 114 | + def filter(self, qs, value): |
| 115 | + try: |
| 116 | + return super().filter(qs, value) |
| 117 | + except (GEOSException, GDALException, ValueError, TypeError) as e: |
| 118 | + raise ValidationError(f"Invalid geometry value: {str(e)}") |
| 119 | + |
103 | 120 | class GeoFilterSet(django_filters.FilterSet): |
104 | 121 | GEOFILTER_FOR_DBFIELD_DEFAULTS = { |
105 | 122 | models.GeometryField: {"filterset_class": GeometryFilter}, |
|
0 commit comments