mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #27962 -- Allowed lookups on Area annotations.
This commit is contained in:
		
				
					committed by
					
						 Tim Graham
						Tim Graham
					
				
			
			
				
	
			
			
			
						parent
						
							e9149d3eb0
						
					
				
				
					commit
					1b1ea63f6a
				
			| @@ -7,6 +7,7 @@ from decimal import Decimal | |||||||
| from django.contrib.gis.db.models.fields import GeoSelectFormatMixin | from django.contrib.gis.db.models.fields import GeoSelectFormatMixin | ||||||
| from django.contrib.gis.geometry.backend import Geometry | from django.contrib.gis.geometry.backend import Geometry | ||||||
| from django.contrib.gis.measure import Area, Distance | from django.contrib.gis.measure import Area, Distance | ||||||
|  | from django.db import models | ||||||
|  |  | ||||||
|  |  | ||||||
| class BaseField: | class BaseField: | ||||||
| @@ -19,11 +20,21 @@ class BaseField: | |||||||
|         return sql, params |         return sql, params | ||||||
|  |  | ||||||
|  |  | ||||||
| class AreaField(BaseField): | class AreaField(models.FloatField): | ||||||
|     "Wrapper for Area values." |     "Wrapper for Area values." | ||||||
|     def __init__(self, area_att=None): |     def __init__(self, area_att=None): | ||||||
|         self.area_att = area_att |         self.area_att = area_att | ||||||
|  |  | ||||||
|  |     def get_prep_value(self, value): | ||||||
|  |         if not isinstance(value, Area): | ||||||
|  |             raise ValueError('AreaField only accepts Area measurement objects.') | ||||||
|  |         return value | ||||||
|  |  | ||||||
|  |     def get_db_prep_value(self, value, connection, prepared=False): | ||||||
|  |         if value is None or not self.area_att: | ||||||
|  |             return value | ||||||
|  |         return getattr(value, self.area_att) | ||||||
|  |  | ||||||
|     def from_db_value(self, value, expression, connection, context): |     def from_db_value(self, value, expression, connection, context): | ||||||
|         if connection.features.interprets_empty_strings_as_nulls and value == '': |         if connection.features.interprets_empty_strings_as_nulls and value == '': | ||||||
|             value = None |             value = None | ||||||
|   | |||||||
| @@ -264,6 +264,19 @@ class GISFunctionsTests(TestCase): | |||||||
|                 result = result.sq_m |                 result = result.sq_m | ||||||
|             self.assertAlmostEqual((result - c.mpoly.area) / c.mpoly.area, 0) |             self.assertAlmostEqual((result - c.mpoly.area) / c.mpoly.area, 0) | ||||||
|  |  | ||||||
|  |     @skipUnlessDBFeature("has_Area_function") | ||||||
|  |     def test_area_lookups(self): | ||||||
|  |         # Create projected countries so the test works on all backends. | ||||||
|  |         CountryWebMercator.objects.bulk_create( | ||||||
|  |             CountryWebMercator(name=c.name, mpoly=c.mpoly.transform(3857, clone=True)) | ||||||
|  |             for c in Country.objects.all() | ||||||
|  |         ) | ||||||
|  |         qs = CountryWebMercator.objects.annotate(area=functions.Area('mpoly')) | ||||||
|  |         self.assertEqual(qs.get(area__lt=Area(sq_km=500000)), CountryWebMercator.objects.get(name='New Zealand')) | ||||||
|  |  | ||||||
|  |         with self.assertRaisesMessage(ValueError, 'AreaField only accepts Area measurement objects.'): | ||||||
|  |             qs.get(area__lt=500000) | ||||||
|  |  | ||||||
|     @skipUnlessDBFeature("has_MakeValid_function") |     @skipUnlessDBFeature("has_MakeValid_function") | ||||||
|     def test_make_valid(self): |     def test_make_valid(self): | ||||||
|         invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))') |         invalid_geom = fromstr('POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user