improve speed of json mixin, add alternate for inserting to history

This commit is contained in:
mixedpuppy 2010-10-20 13:03:58 -07:00
Родитель 83c2d581f1
Коммит 3f8d225a3e
4 изменённых файлов: 24 добавлений и 48 удалений

Просмотреть файл

@ -32,7 +32,7 @@ OAuth authorization api.
@json_exception_response
def get(self, domain=None):
keys = [k for k in session.get('account_keys', '').split(',') if k]
return [session[k].get('profile') for k in keys]
return [p for p in [session[k].get('profile') for k in keys] if p]
def signout(self):
domain = request.params.get('domain')

Просмотреть файл

@ -98,6 +98,15 @@ The 'send' namespace is used to send updates to our supported services.
# create a new record in the history table.
assert result
if asbool(config.get('history_enabled', True)):
# this is faster, but still want to look further into SA perf
#data = {
# 'json_attributes': json.dumps(dict(request.POST)),
# 'account_id': acct.get('id'),
# 'published': UTCDateTime.now()
#}
#Session.execute("INSERT DELAYED INTO history (json_attributes, account_id, published) VALUES (:json_attributes, :account_id, :published)",
# data)
history = History()
history.account_id = acct.get('id')
history.published = UTCDateTime.now()

Просмотреть файл

@ -6,42 +6,27 @@
import json
from sqlalchemy.orm.interfaces import MapperExtension, EXT_CONTINUE
from sqlalchemy import Column, Text
from sqlalchemy import types
# A mapper extension to help us with 'expandos' magic - ensures that expando
# attributes set via normal 'object.expando=value' syntax is reflected
# back into the json_attributes column.
class _ExpandoFlushingExtension(MapperExtension):
def before_insert(self, mapper, connection, instance):
instance._flush_expandos()
return EXT_CONTINUE
class Json(types.TypeDecorator, types.MutableType):
impl=types.Text
before_update = before_insert
def process_bind_param(self, value, dialect):
return json.dumps(value)
def process_result_value(self, value, dialect):
return json.loads(value)
# The actual mixin class
class JsonExpandoMixin(object):
__mapper_args__ = {'extension': _ExpandoFlushingExtension()}
json_attributes = Column(Text)
# Methods for providing 'expandos' via the json_attributes field.
def _get_expando_namespace(self):
if '_expando_namespace' not in self.__dict__:
assert '_orig_json' not in self.__dict__
attrs = self.json_attributes
self.__dict__['_orig_json'] = attrs
if not attrs:
_expando_namespace = {}
else:
_expando_namespace = json.loads(attrs)
self.__dict__['_expando_namespace'] = _expando_namespace
return self.__dict__['_expando_namespace']
json_attributes = Column(Json)
def __getattr__(self, name):
if name.startswith('_'):
raise AttributeError(name)
# is it in the namespace?
try:
return self._get_expando_namespace()[name]
return self.json_attributes[name]
except KeyError:
raise AttributeError(name)
@ -52,30 +37,12 @@ class JsonExpandoMixin(object):
# assume it is an 'expando' object
# Set json attributes to itself simply so the object is marked as
# 'dirty' for subsequent updates.
self.json_attributes = self.json_attributes
self._get_expando_namespace()[name] = value
self.json_attributes = self.json_attributes or {}
self.json_attributes[name] = value
def __delattr__(self, name):
try:
del self._get_expando_namespace()[name]
del self.json_attributes[name]
self.json_attributes = self.json_attributes # to mark as dirty
except KeyError:
raise AttributeError("'%s' is not an 'expando' property" % (name,))
# Note that you should never need to call this function manually - a
# mapper extension is defined above which calls this function before
# the object is saved.
def _flush_expandos(self):
try:
en = self.__dict__['_expando_namespace']
except KeyError:
# no property accesses at all
return
if self._orig_json != self.json_attributes:
# This means someone used 'expandos' *and* explicitly set
# json_attributes on the same object.
raise ValueError("object's json_attributes have changed externally")
self.json_attributes = None if not en else json.dumps(en)
# and reset the world back to as if expandos have never been set.
del self.__dict__['_orig_json']
del self.__dict__['_expando_namespace']

Просмотреть файл

@ -28,10 +28,10 @@ class SerializerMixin(object):
val = val.isoformat().split('.')[0].replace('+00:00','')+'Z'
if prop.key == 'json_attributes':
propdict.update(json.loads(val))
propdict.update(val)
else:
propdict[prop.key] = val
elif prop.key != 'json_attributes':
else:
propdict[prop.key] = val
for val in self._rd_collection_to_dict('tags', fields):