Skip to content

Conversation

@NoahStapp
Copy link
Contributor

No description provided.

Comment on lines 60 to 62
"GIS Union not supported.": {
"gis_tests.geoapp.tests.GeoLookupTest.test_gis_lookups_with_complex_expressions",
},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self that we should add @skipUnlessDBFeature("supports_Union_function") and send the patch upstream. I'll hold off in case any more similar changes are identified by this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a couple other places where tests not marked as requiring a feature use it. Maybe the authors didn't expect a backend to implement only the slice of operations that we do?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. The skipping is generally just best effort... what's needed for the built-in backends.

@NoahStapp
Copy link
Contributor Author

All tests (including some simple ones I added due to many of the Django ones requiring features we don't support) passing, marking as ready for an initial review pass.

@NoahStapp NoahStapp marked this pull request as ready for review November 20, 2025 22:16
Copy link
Collaborator

@timgraham timgraham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation to update is docs/ref/contrib/gis.rst.

@timgraham timgraham changed the title Initial GeoSpatial query support INTPYTHON-835 Add support for GIS lookups Nov 21, 2025
@NoahStapp NoahStapp requested a review from timgraham November 24, 2025 16:06
Copy link
Collaborator

@timgraham timgraham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you forget the documentation updates? :-)

Comment on lines 21 to 22
self.assertEqual(qs.count(), 1)
self.assertEqual(houston, qs.first())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer self.assertCountEqual(qs, [houston])
QuerySet.count() adds an extra query and makes a failure more difficult to debug since the first thing you need to do is run the test to find which extra objects appeared.
Also, in Django tests, the expected values usually appear as the second argument.

@timgraham

This comment was marked as resolved.

def gis_lookup(self, compiler, connection, as_expr=False): # noqa: ARG001
raise NotSupportedError(f"MongoDB does not support the {self.lookup_name} lookup.")

def gis_lookup(self, compiler, connection, as_expr=False):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the geo operator like $geoWithin and other inside an $expr?
As long as I know we can't, so we should raise an error if the as_expr is True I have fear that someone tries to wrap a gis_lookup inside a Case and the query fails

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test for the exception and document all limitations of these lookups (no subqueries, no expressions).

@NoahStapp

This comment was marked as resolved.

@NoahStapp NoahStapp requested review from WaVEV and timgraham and removed request for timgraham December 1, 2025 14:21
models.Union,
)

operators = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simply use:

Suggested change
operators = {
gis_operators = {

It's a property on databases where some logic based on database version is needed to determine what operators are available.

houston = City.objects.get(name="Houston")
dallas = City.objects.get(name="Dallas") # Roughly ~363 km from Houston
qs = City.objects.filter(point__distance_lte=(houston.point, 362826))
self.assertCountEqual(list(qs), [houston, dallas])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list() isn't needed with assertCountEqual()

Comment on lines 63 to 64
qs = City.objects.filter(point__dwithin=(houston.point, 0.2))
self.assertEqual(qs.count(), 5)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about asserting the results and not using count applies to other tests. In this case, you could use City.objects.exclude() to produce fewer results.

def test_within(self):
zipcode = Zipcode.objects.get(code="77002")
qs = City.objects.filter(point__within=zipcode.poly).values_list("name", flat=True)
self.assertEqual(list(qs), ["Houston"])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.assertCountEqual(qs, ["Houston"]) also works if you want be consistent with the other tests.

return self.name, []


class Within(Operator):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please alphabetize the subclasses.

@NoahStapp NoahStapp requested a review from timgraham December 5, 2025 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants