From a4f9ef4fe8048264c5d9e193e2ff79f735626c65 Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Tue, 7 Nov 2017 19:49:29 +0500 Subject: [PATCH] Refs #28518 -- Improved performance of assigning values to GeometryFields. --- django/contrib/gis/db/models/fields.py | 2 +- django/contrib/gis/db/models/proxy.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/django/contrib/gis/db/models/fields.py b/django/contrib/gis/db/models/fields.py index e43d7ccc2ed..f0329b2ec12 100644 --- a/django/contrib/gis/db/models/fields.py +++ b/django/contrib/gis/db/models/fields.py @@ -247,7 +247,7 @@ class GeometryField(BaseSpatialField): super().contribute_to_class(cls, name, **kwargs) # Setup for lazy-instantiated Geometry object. - setattr(cls, self.attname, SpatialProxy(GEOSGeometry, self)) + setattr(cls, self.attname, SpatialProxy(self.geom_class or GEOSGeometry, self, load_func=GEOSGeometry)) def formfield(self, **kwargs): defaults = {'form_class': self.form_class, diff --git a/django/contrib/gis/db/models/proxy.py b/django/contrib/gis/db/models/proxy.py index 3c306cceb0c..06d64873d99 100644 --- a/django/contrib/gis/db/models/proxy.py +++ b/django/contrib/gis/db/models/proxy.py @@ -9,13 +9,14 @@ from django.db.models.query_utils import DeferredAttribute class SpatialProxy(DeferredAttribute): - def __init__(self, klass, field): + def __init__(self, klass, field, load_func=None): """ Initialize on the given Geometry or Raster class (not an instance) and the corresponding field. """ self._field = field self._klass = klass + self._load_func = load_func or klass super().__init__(field.attname, klass) def __get__(self, instance, cls=None): @@ -42,7 +43,7 @@ class SpatialProxy(DeferredAttribute): else: # Otherwise, a geometry or raster object is built using the field's # contents, and the model's corresponding attribute is set. - geo_obj = self._klass(geo_value) + geo_obj = self._load_func(geo_value) setattr(instance, self._field.attname, geo_obj) return geo_obj @@ -61,7 +62,7 @@ class SpatialProxy(DeferredAttribute): # For raster fields, assure input is None or a string, dict, or # raster instance. pass - elif isinstance(value, self._klass) and (str(value.geom_type).upper() == gtype or gtype == 'GEOMETRY'): + elif isinstance(value, self._klass): # The geometry type must match that of the field -- unless the # general GeometryField is used. if value.srid is None: