How to overwrite put () method on python application kernel model?

In Appengine, I try to get a property value calculated automatically and saved with the object.

I have a class, Rectangle, and it has width, height and area. Obviously, a region is a function of width and height, but I want it to be a property because I want to use it for sorting. Therefore, I am trying to modify the put () function to sneak an area while saving a Rectangle as follows:

class Rectangle(db.Model): width = db.IntegerProperty() height = db.IntegerProperty() area = db.IntegerProperty() def put(self, **kwargs): self.area = self.width * self.height super(Rectangle, self).put(**kwargs) 

This works when I call put() directly on the Area object:

 re1 = Rectangle(width=10, height=10) re1.put() print re1.area # >> 10 

But when I use db.put() (for example, to save a lot of them at once), it breaks.

 re2 = Rectangle(width=5, height=5) db.put(re2) print re2.area # >> None 

What is the correct way to color a calculated value?

+6
source share
2 answers

Do not override put - as you notice, it is fragile and is not called if you call db.put instead of the put put function.

Fortunately, App Engine provides ComputedProperty , which makes your use case very simple:

 class Rectangle(db.Model): width = db.IntegerProperty() height = db.IntegerProperty() @db.ComputedProperty def area(self): return self.width * self.height 
+7
source

I agree that ComputedProperty is the way to describe this specific scenario. However, it would be useful to overload the put function. For example, we use the following code to track all callers who provide data warehouse data so that we can easily debug peaks during recording.

 from google.appengine.ext import db _orig_db_put_async = db.put_async _orig_db_model_put = db.Model.put def _new_db_put_async(models, *args, **kwargs): """Instrumented version of db.put_async (which db.put also calls).""" retval = _orig_db_put_async(models, *args, **kwargs) msg = ['query: %s' % _get_caller()] # 'models' can be either a single model instance, or a list of them. try: for model in models: msg.append(model.__class__.__name__ + '.<db.put>') except TypeError: msg.append(models.__class__.__name__ + '.<db.put>') instance_cache.increment(' -- '.join(msg)) return retval def _new_db_model_put(self, *args, **kwargs): """Like entity.put() but stores put-stats in the instance cache.""" retval = _orig_db_model_put(self, *args, **kwargs) msg = ['query: %s' % _get_caller()] msg.append(self.__class__.__name__ + '.<put>') instance_cache.increment(' -- '.join(msg)) return retval 

This code stores a counter, from which code files provide records in memcache, and then periodically deletes it in the logs. The log lines look something like this:

3041: activity_summary.py:312 -- UserData.<put>

Where 3041 is the number of lines 312 for Activity_summary.py issued by UserData.put() .

+1
source

Source: https://habr.com/ru/post/898144/


All Articles