general: cache substitution variables in requests (#22107)
This commit is contained in:
parent
d686c0841f
commit
95651fc809
|
@ -359,6 +359,7 @@ def test_dispatch_auto(pub):
|
|||
item.dispatch_type = 'automatic'
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
pub.substitutions.reset()
|
||||
pub.substitutions.feed(formdata)
|
||||
item.perform(formdata)
|
||||
assert not formdata.workflow_roles
|
||||
|
@ -375,21 +376,29 @@ def test_dispatch_auto(pub):
|
|||
{'role_id': role2.id, 'value': 'bar'},
|
||||
]
|
||||
|
||||
pub.substitutions.reset()
|
||||
pub.substitutions.feed(formdata)
|
||||
item.perform(formdata)
|
||||
assert not formdata.workflow_roles
|
||||
|
||||
# no match
|
||||
formdata.data = {'1': 'XXX'}
|
||||
pub.substitutions.reset()
|
||||
pub.substitutions.feed(formdata)
|
||||
item.perform(formdata)
|
||||
assert not formdata.workflow_roles
|
||||
|
||||
# match
|
||||
formdata.data = {'1': 'foo'}
|
||||
pub.substitutions.reset()
|
||||
pub.substitutions.feed(formdata)
|
||||
item.perform(formdata)
|
||||
assert formdata.workflow_roles == {'_receiver': role1.id}
|
||||
|
||||
# other match
|
||||
formdata.data = {'1': 'bar'}
|
||||
pub.substitutions.reset()
|
||||
pub.substitutions.feed(formdata)
|
||||
item.perform(formdata)
|
||||
assert formdata.workflow_roles == {'_receiver': role2.id}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
import time
|
||||
import random
|
||||
|
@ -1569,6 +1570,7 @@ class PageField(Field):
|
|||
# backward compatibility. They are not added globally as they would
|
||||
# interfere with the var_ prefixed variables used in dynamic jsonp
|
||||
# fields. (#9786)
|
||||
data = copy.copy(data)
|
||||
data.update(live_data)
|
||||
|
||||
try:
|
||||
|
|
|
@ -29,7 +29,7 @@ from qommon import _
|
|||
from qommon.storage import StorableObject, Intersects, Contains
|
||||
import qommon.misc
|
||||
from qommon.evalutils import make_datetime
|
||||
from qommon.substitution import Substitutions
|
||||
from qommon.substitution import Substitutions, invalidate_substitution_cache
|
||||
from qommon.template import Template
|
||||
|
||||
from roles import Role
|
||||
|
@ -290,6 +290,7 @@ class FormData(StorableObject):
|
|||
if changed:
|
||||
self.store()
|
||||
|
||||
@invalidate_substitution_cache
|
||||
def store(self, *args, **kwargs):
|
||||
# make sure the class set under the formdef name in the sys.modules
|
||||
# namespaces is the exact one that was used when creating this
|
||||
|
|
|
@ -14,8 +14,19 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from quixote import get_request
|
||||
from quixote.html import htmltext, TemplateIO
|
||||
|
||||
|
||||
def invalidate_substitution_cache(func):
|
||||
def f(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
finally:
|
||||
Substitutions.invalidate_cache()
|
||||
return f
|
||||
|
||||
|
||||
class Substitutions(object):
|
||||
substitutions_dict = {}
|
||||
dynamic_sources = []
|
||||
|
@ -41,9 +52,11 @@ class Substitutions(object):
|
|||
cls.dynamic_sources = []
|
||||
cls.dynamic_sources.append(klass)
|
||||
|
||||
@invalidate_substitution_cache
|
||||
def reset(self):
|
||||
self.sources = []
|
||||
|
||||
@invalidate_substitution_cache
|
||||
def feed(self, source):
|
||||
if source is None:
|
||||
# silently ignore a None source, this is for example useful when
|
||||
|
@ -52,10 +65,22 @@ class Substitutions(object):
|
|||
return
|
||||
self.sources.append(source)
|
||||
|
||||
@classmethod
|
||||
def invalidate_cache(cls):
|
||||
request = get_request()
|
||||
if hasattr(request, '_cache_context_variables'):
|
||||
delattr(request, '_cache_context_variables')
|
||||
|
||||
def get_context_variables(self):
|
||||
request = get_request()
|
||||
d = getattr(request, '_cache_context_variables', None)
|
||||
if d is not None:
|
||||
return d
|
||||
d = {}
|
||||
for source in self.sources:
|
||||
d.update(source.get_substitution_variables())
|
||||
if request:
|
||||
request._cache_context_variables = d
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -24,6 +24,7 @@ import cPickle
|
|||
from quixote import get_publisher
|
||||
import qommon
|
||||
from qommon.storage import _take, parse_clause as parse_storage_clause
|
||||
from qommon.substitution import invalidate_substitution_cache
|
||||
from qommon import get_cfg
|
||||
|
||||
import wcs.categories
|
||||
|
@ -1185,6 +1186,7 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
|
|||
cur.close()
|
||||
|
||||
@guard_postgres
|
||||
@invalidate_substitution_cache
|
||||
def store(self):
|
||||
sql_dict = {
|
||||
'user_id': self.user_id,
|
||||
|
@ -1508,6 +1510,7 @@ class SqlUser(SqlMixin, wcs.users.User):
|
|||
self.roles = []
|
||||
|
||||
@guard_postgres
|
||||
@invalidate_substitution_cache
|
||||
def store(self):
|
||||
sql_dict = {
|
||||
'name': self.name,
|
||||
|
@ -1691,6 +1694,7 @@ class TrackingCode(SqlMixin, wcs.tracking_code.TrackingCode):
|
|||
id = None
|
||||
|
||||
@guard_postgres
|
||||
@invalidate_substitution_cache
|
||||
def store(self):
|
||||
sql_dict = {
|
||||
'id': self.id,
|
||||
|
|
|
@ -20,7 +20,7 @@ from qommon.storage import StorableObject
|
|||
from qommon import get_cfg
|
||||
import wcs.qommon.storage as st
|
||||
|
||||
from qommon.substitution import Substitutions
|
||||
from qommon.substitution import Substitutions, invalidate_substitution_cache
|
||||
|
||||
class User(StorableObject):
|
||||
_names = 'users'
|
||||
|
@ -66,6 +66,10 @@ class User(StorableObject):
|
|||
if changed:
|
||||
self.store()
|
||||
|
||||
@invalidate_substitution_cache
|
||||
def store(self, *args, **kwargs):
|
||||
return super(User, self).store(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_formdef(cls):
|
||||
from admin.settings import UserFieldsFormDef
|
||||
|
|
Loading…
Reference in New Issue