Один из способов сделать это быстрее - это превратить вашу модель в словарь и использовать встроенную функцию eval / repr в качестве (de) сериализаторов - с осторожностью, конечно, как всегда для злого eval, но это должно бытьЗдесь безопасно, поскольку нет внешнего шага.
Ниже приведен пример реализации класса Fake_entity.Сначала вы создаете свой словарь с помощью fake = Fake_entity(entity)
, затем вы можете просто сохранить свои данные с помощью memcache.set(key, fake.serialize())
.Serialize () - это простой вызов родного словарного метода repr, с некоторыми добавлениями, если вам нужно (например, добавить идентификатор в начале строки).
Чтобы получить его обратно, просто используйте fake = Fake_entity(memcache.get(key))
.Объект Fake_entity - это простой словарь, ключи которого также доступны в качестве атрибутов.Вы можете получить доступ к свойствам вашей сущности в обычном режиме, за исключением того, что referenceProperties дают ключи вместо выборки объекта (что на самом деле весьма полезно).Вы также можете получить () фактическую сущность с помощью fake.get () или, что более интересно, изменить ее и затем сохранить с помощью fake.put ().
Она не работает со списками (если вы выбираете несколько сущностей)из запроса), но может быть легко отрегулирован с помощью функций соединения / разделения с использованием идентификатора, подобного '### FAKE MODEL ENTITY ###' в качестве разделителя.Используйте только с db.Model, для Expando потребуются небольшие корректировки.
class Fake_entity(dict):
def __init__(self, record):
# simple case: a string, we eval it to rebuild our fake entity
if isinstance(record, basestring):
import datetime # <----- put all relevant eval imports here
from google.appengine.api import datastore_types
self.update( eval(record) ) # careful with external sources, eval is evil
return None
# serious case: we build the instance from the actual entity
for prop_name, prop_ref in record.__class__.properties().items():
self[prop_name] = prop_ref.get_value_for_datastore(record) # to avoid fetching entities
self['_cls'] = record.__class__.__module__ + '.' + record.__class__.__name__
try:
self['key'] = str(record.key())
except Exception: # the key may not exist if the entity has not been stored
pass
def __getattr__(self, k):
return self[k]
def __setattr__(self, k, v):
self[k] = v
def key(self):
from google.appengine.ext import db
return db.Key(self['key'])
def get(self):
from google.appengine.ext import db
return db.get(self['key'])
def put(self):
_cls = self.pop('_cls') # gets and removes the class name form the passed arguments
# import xxxxxxx ---> put your model imports here if necessary
Cls = eval(_cls) # make sure that your models declarations are in the scope here
real_entity = Cls(**self) # creates the entity
real_entity.put() # self explanatory
self['_cls'] = _cls # puts back the class name afterwards
return real_entity
def serialize(self):
return '### FAKE MODEL ENTITY ###\n' + repr(self)
# or simply repr, but I use the initial identifier to test and eval directly when getting from memcache
Я бы приветствовал тесты скорости на этом, я бы предположил, что это намного быстрее, чем другие подходы.Кроме того, у вас нет никаких рисков, если ваши модели каким-то образом изменились за это время.
Ниже приведен пример того, как выглядит сериализованная поддельная сущность.Посмотрите на дату и время (созданные), а также на свойства ссылок (поддомен):
### FAKE MODEL ENTITY ###
{'status': u'admin ',' session_expiry ': None,'first_name ': u'Louis', 'last_name': u'Le Sieur ','ified_by': None, 'password_hash': u'a9993e364706816aba3e25717000000000000000 ',' language ': u'fr', 'созданный': datetime.datetime (2010, 7, 18, 21, 50, 11, 750000), «изменено»: нет, «создано»: нет, «электронная почта»: u'chou@glou.bou »,« ключ »:« agdqZXJlZ2xlcgwLEgVMb2dpbhjmAQw »,« session_ref »': None,' _cls ':' models.Login ',' groups ': [],' email___password_hash ': u'chou@glou.bou+a9993e364706816aba3e2571700000000000000000', 'subdomain': datastore_types.Key.from_path uname (, 229L, _app = u'jeregle '),' разрешено ': [],' permissions ': []}
Лично я также использую статические переменные (быстрее чем memcache) для кэширования своих сущностей в краткосрочной перспективеи получить хранилище данных, когда сервер изменился или его память по какой-то причине была очищена (что часто случается вфакт).