Refs #28518 -- Improved performance of assigning values to GeometryFields.

This commit is contained in:
Sergey Fedoseev 2017-11-07 19:49:29 +05:00 committed by Tim Graham
parent c69e4bc691
commit a4f9ef4fe8
2 changed files with 5 additions and 4 deletions

View File

@ -247,7 +247,7 @@ class GeometryField(BaseSpatialField):
super().contribute_to_class(cls, name, **kwargs) super().contribute_to_class(cls, name, **kwargs)
# Setup for lazy-instantiated Geometry object. # 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): def formfield(self, **kwargs):
defaults = {'form_class': self.form_class, defaults = {'form_class': self.form_class,

View File

@ -9,13 +9,14 @@ from django.db.models.query_utils import DeferredAttribute
class SpatialProxy(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) Initialize on the given Geometry or Raster class (not an instance)
and the corresponding field. and the corresponding field.
""" """
self._field = field self._field = field
self._klass = klass self._klass = klass
self._load_func = load_func or klass
super().__init__(field.attname, klass) super().__init__(field.attname, klass)
def __get__(self, instance, cls=None): def __get__(self, instance, cls=None):
@ -42,7 +43,7 @@ class SpatialProxy(DeferredAttribute):
else: else:
# Otherwise, a geometry or raster object is built using the field's # Otherwise, a geometry or raster object is built using the field's
# contents, and the model's corresponding attribute is set. # 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) setattr(instance, self._field.attname, geo_obj)
return geo_obj return geo_obj
@ -61,7 +62,7 @@ class SpatialProxy(DeferredAttribute):
# For raster fields, assure input is None or a string, dict, or # For raster fields, assure input is None or a string, dict, or
# raster instance. # raster instance.
pass 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 # The geometry type must match that of the field -- unless the
# general GeometryField is used. # general GeometryField is used.
if value.srid is None: if value.srid is None: