Skip to content

Commit 9344785

Browse files
committed
Add GeoDjango support
1 parent 1471eca commit 9344785

File tree

7 files changed

+182
-0
lines changed

7 files changed

+182
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .functions import register_functions
2+
3+
register_functions()

django_mongodb_backend_gis/adapter.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import collections
2+
3+
4+
class Adapter(collections.UserDict):
5+
def __init__(self, obj, geography=False):
6+
"""
7+
Initialize on the spatial object.
8+
"""
9+
self.data = {
10+
"type": obj.__class__.__name__,
11+
"coordinates": obj.coords,
12+
}

django_mongodb_backend_gis/base.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django_mongodb_backend.base import DatabaseWrapper as BaseDatabaseWrapper
2+
3+
from .features import DatabaseFeatures
4+
from .operations import DatabaseOperations
5+
from .schema import DatabaseSchemaEditor
6+
7+
8+
class DatabaseWrapper(BaseDatabaseWrapper):
9+
SchemaEditorClass = DatabaseSchemaEditor
10+
features_class = DatabaseFeatures
11+
ops_class = DatabaseOperations
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from django.contrib.gis.db.backends.base.features import BaseSpatialFeatures
2+
from django.utils.functional import cached_property
3+
4+
from django_mongodb_backend.features import DatabaseFeatures as MongoFeatures
5+
6+
7+
class DatabaseFeatures(BaseSpatialFeatures, MongoFeatures):
8+
has_spatialrefsys_table = False
9+
supports_transform = False
10+
11+
@cached_property
12+
def django_test_expected_failures(self):
13+
expected_failures = super().django_test_expected_failures
14+
expected_failures.update(
15+
{
16+
# SRIDs aren't supported.
17+
"gis_tests.geogapp.tests.GeographyTest.test05_geography_layermapping",
18+
# 'WithinLookup' object has no attribute 'as_mql'
19+
# "gis_tests.relatedapp.tests.RelatedGeoModelTest.test10_combine",
20+
# GEOSException: Calling transform() with no SRID set is not supported
21+
"gis_tests.relatedapp.tests.RelatedGeoModelTest.test06_f_expressions",
22+
# To triage:
23+
"gis_tests.geoapp.test_expressions.GeoExpressionsTests.test_geometry_value_annotation",
24+
"gis_tests.geoapp.test_expressions.GeoExpressionsTests.test_multiple_annotation",
25+
"gis_tests.geoapp.test_regress.GeoRegressionTests.test_empty_count",
26+
"gis_tests.geoapp.test_serializers.GeoJSONSerializerTests.test_fields_option",
27+
"gis_tests.geoapp.test_serializers.GeoJSONSerializerTests.test_geometry_field_option",
28+
"gis_tests.geoapp.test_serializers.GeoJSONSerializerTests.test_id_field_option",
29+
"gis_tests.geoapp.test_serializers.GeoJSONSerializerTests.test_serialization_base",
30+
"gis_tests.geoapp.test_serializers.GeoJSONSerializerTests.test_srid_option",
31+
"gis_tests.geoapp.tests.GeoLookupTest.test_contains_contained_lookups",
32+
"gis_tests.geoapp.tests.GeoLookupTest.test_disjoint_lookup",
33+
"gis_tests.geoapp.tests.GeoLookupTest.test_equals_lookups",
34+
"gis_tests.geoapp.tests.GeoLookupTest.test_null_geometries",
35+
"gis_tests.geoapp.tests.GeoLookupTest.test_subquery_annotation",
36+
"gis_tests.geoapp.tests.GeoModelTest.test_geometryfield",
37+
"gis_tests.geoapp.tests.GeoModelTest.test_gis_query_as_string",
38+
"gis_tests.geoapp.tests.GeoQuerySetTest.test_within_subquery",
39+
"gis_tests.geoapp.test_expressions.GeoExpressionsTests.test_update_from_other_field",
40+
"gis_tests.geoapp.tests.GeoLookupTest.test_gis_lookups_with_complex_expressions",
41+
"gis_tests.geoapp.tests.GeoModelTest.test_proxy",
42+
}
43+
)
44+
return expected_failures
45+
46+
@cached_property
47+
def django_test_skips(self):
48+
skips = super().django_test_skips
49+
skips.update(
50+
{
51+
"inspectdb not supported.": {
52+
"gis_tests.inspectapp.tests.InspectDbTests",
53+
},
54+
"Raw SQL not supported": {
55+
"gis_tests.geoapp.tests.GeoModelTest.test_raw_sql_query",
56+
},
57+
},
58+
)
59+
return skips
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.contrib.gis.db.models.functions import Distance, Length, Perimeter
2+
3+
4+
def register_functions():
5+
Distance.as_cockroachdb = Distance.as_postgresql
6+
Length.as_cockroachdb = Length.as_postgresql
7+
Perimeter.as_cockroachdb = Perimeter.as_postgresql
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from django.contrib.gis import geos
2+
from django.contrib.gis.db import models
3+
from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations
4+
5+
from django_mongodb_backend.operations import (
6+
DatabaseOperations as MongoOperations,
7+
)
8+
9+
from .adapter import Adapter
10+
11+
12+
class DatabaseOperations(BaseSpatialOperations, MongoOperations):
13+
Adapter = Adapter
14+
15+
disallowed_aggregates = (
16+
models.Collect,
17+
models.Extent,
18+
models.Extent3D,
19+
models.MakeLine,
20+
models.Union,
21+
)
22+
23+
@property
24+
def gis_operators(self):
25+
return {}
26+
27+
unsupported_functions = {
28+
"Area",
29+
"AsGeoJSON",
30+
"AsGML",
31+
"AsKML",
32+
"AsSVG",
33+
"AsWKB",
34+
"AsWKT",
35+
"Azimuth",
36+
"BoundingCircle",
37+
"Centroid",
38+
"ClosestPoint",
39+
"Difference",
40+
"Distance",
41+
"Envelope",
42+
"ForcePolygonCW",
43+
"FromWKB",
44+
"FromWKT",
45+
"GeoHash",
46+
"GeometryDistance",
47+
"Intersection",
48+
"IsEmpty",
49+
"IsValid",
50+
"Length",
51+
"LineLocatePoint",
52+
"MakeValid",
53+
"MemSize",
54+
"NumGeometries",
55+
"NumPoints",
56+
"Perimeter",
57+
"PointOnSurface",
58+
"Reverse",
59+
"Scale",
60+
"SnapToGrid",
61+
"SymDifference",
62+
"Transform",
63+
"Translate",
64+
"Union",
65+
}
66+
67+
def geo_db_type(self, f):
68+
return "object"
69+
70+
def get_geometry_converter(self, expression):
71+
geom_class = expression.output_field.geom_class
72+
73+
def converter(value, expression, connection): # noqa: ARG001
74+
if value is None:
75+
return None
76+
if issubclass(geom_class, geos.GeometryCollection):
77+
init_val = [
78+
geom_class._allowed(value["coordinates"][x][0])
79+
for x in range(len(value["coordinates"]))
80+
]
81+
else:
82+
init_val = value["coordinates"]
83+
return geom_class(init_val)
84+
85+
return converter

django_mongodb_backend_gis/schema.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django_mongodb_backend.schema import DatabaseSchemaEditor as BaseSchemaEditor
2+
3+
4+
class DatabaseSchemaEditor(BaseSchemaEditor):
5+
pass

0 commit comments

Comments
 (0)