En el siguiente ejemplo, cached_attr
se usa para obtener o establecer un atributo en una instancia modelo cuando se llama a una propiedad de base de datos costosa (related_spam
en el ejemplo). En el ejemplo, uso cached_spam
para guardar consultas. Puse declaraciones de impresión al configurar y cuando recibo valores para poder probarlo. Lo probé en una vista pasando una instancia de Egg
en la vista y en la vista usando {{ egg.cached_spam }}
, así como en otros métodos del modelo Egg
que hacen llamadas a cached_spam
. Cuando terminé y lo probé, la salida de shell en el servidor de desarrollo de Django mostró que la memoria caché de atributos se había omitido varias veces, y que se había obtenido varias veces con éxito. Parece ser inconsistente. Con los mismos datos, cuando hice pequeños cambios (tan poco como cambiar la secuencia de la instrucción de impresión) y los actualicé (con todos los mismos datos), ocurrieron diferentes cantidades de errores/éxitos. ¿Cómo y por qué está sucediendo esto? ¿Es este código incorrecto o altamente problemático?Python: almacenamiento en caché de una propiedad para evitar cálculos futuros
class Egg(models.Model):
... fields
@property
def related_spam(self):
# Each time this property is called the database is queried (expected).
return Spam.objects.filter(egg=self).all() # Spam has foreign key to Egg.
@property
def cached_spam(self):
# This should call self.related_spam the first time, and then return
# cached results every time after that.
return self.cached_attr('related_spam')
def cached_attr(self, attr):
"""This method (normally attached via an abstract base class, but put
directly on the model for this example) attempts to return a cached
version of a requested attribute, and calls the actual attribute when
the cached version isn't available."""
try:
value = getattr(self, '_p_cache_{0}'.format(attr))
print('GETTING - {0}'.format(value))
except AttributeError:
value = getattr(self, attr)
print('SETTING - {0}'.format(value))
setattr(self, '_p_cache_{0}'.format(attr), value)
return value
Me encontré con esta molestia y me di cuenta de que otra forma de resolver este problema es usar la etiqueta de la plantilla 'with' para crear un alias para un resultado calculado. – nedned
@humble - thx, eso es realmente una nota bastante útil. – orokusaki