From 1777736e06ad6cf8011d094e9a9ac227b8e1072a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Sun, 28 Jun 2020 09:07:05 +0200
Subject: [PATCH 2/2] general: add template access to cards and forms (#43328)

---
 tests/test_carddef.py      | 22 ++++++++++++++++++++++
 tests/test_formdata.py     | 31 +++++++++++++++++++++++++++++++
 wcs/qommon/substitution.py |  3 ++-
 wcs/variables.py           | 31 +++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/tests/test_carddef.py b/tests/test_carddef.py
index e562fa58f..aa28d2116 100644
--- a/tests/test_carddef.py
+++ b/tests/test_carddef.py
@@ -1,6 +1,7 @@
 import pytest
 
 from wcs.qommon.http_request import HTTPRequest
+from wcs.qommon.template import Template
 from wcs.carddef import CardDef
 from wcs.fields import StringField
 
@@ -74,3 +75,24 @@ def test_xml_export_import(pub):
 
     carddef2 = CardDef.import_from_xml_tree(carddef_xml)
     assert carddef2.name == 'foo'
+
+
+def test_template_access(pub):
+    CardDef.wipe()
+    carddef = CardDef()
+    carddef.name = 'foo'
+    carddef.fields = [
+        StringField(id='1', label='Test', type='string', varname='foo'),
+    ]
+    carddef.store()
+    carddef.data_class().wipe()
+
+    for i in range(10):
+        carddata = carddef.data_class()()
+        carddata.data = {'1': 'blah'}
+        carddata.just_created()
+        carddata.store()
+
+    context = pub.substitutions.get_context_variables(mode='lazy')
+    tmpl = Template('{{cards.foo.objects|filter_by:"foo"|filter_value:"blah"|count}}')
+    assert tmpl.render(context) == '10'
diff --git a/tests/test_formdata.py b/tests/test_formdata.py
index a1ed08fdf..84160b437 100644
--- a/tests/test_formdata.py
+++ b/tests/test_formdata.py
@@ -929,6 +929,37 @@ def test_lazy_formdata_queryset_filter(pub, variable_test_data):
     assert tmpl.render(context) == '7'
 
 
+def test_lazy_global_forms(pub, variable_test_data):
+    lazy_formdata = variable_test_data
+    formdef = lazy_formdata._formdef
+    formdef.store()
+    data_class = lazy_formdata._formdef.data_class()
+    for i in range(6):
+        formdata = data_class()
+        formdata.data = {'0': 'bar'}
+        formdata.just_created()
+        formdata.store()
+    for i in range(4):
+        formdata = data_class()
+        formdata.data = {'0': 'foo'}
+        formdata.just_created()
+        formdata.jump_status('finished')
+        formdata.store()
+
+    formdata = data_class()
+    formdata.data = {'0': 'bar'}
+    formdata.status = 'draft'
+    formdata.store()
+
+    # template tags
+    context = pub.substitutions.get_context_variables(mode='lazy')
+    tmpl = Template('{{forms.foobarlazy.slug}}')
+    assert tmpl.render(context) == 'foobarlazy'
+
+    tmpl = Template('{{forms.foobarlazy.objects|filter_by:"foo_foo"|filter_value:"bar"|count}}')
+    assert tmpl.render(context) == '7'
+
+
 def test_lazy_variables(pub, variable_test_data):
     formdata = FormDef.select()[0].data_class().select()[0]
     for mode in (None, 'lazy'):
diff --git a/wcs/qommon/substitution.py b/wcs/qommon/substitution.py
index 3c3e89f35..3ee852237 100644
--- a/wcs/qommon/substitution.py
+++ b/wcs/qommon/substitution.py
@@ -41,9 +41,10 @@ class Substitutions(object):
 
     def set_empty(self):
         from wcs.data_sources import NamedDataSource
+        from wcs.variables import CardsSource, FormsSource
         from wcs.wscalls import NamedWsCall
         from wcs.scripts import Script
-        self.sources = [NamedDataSource, NamedWsCall, Script]
+        self.sources = [NamedDataSource, NamedWsCall, CardsSource, FormsSource, Script]
 
     @classmethod
     def register(cls, varname, category=None, comment=None):
diff --git a/wcs/variables.py b/wcs/variables.py
index 5aa1452ba..1cae10d89 100644
--- a/wcs/variables.py
+++ b/wcs/variables.py
@@ -29,6 +29,7 @@ from .qommon.evalutils import make_datetime
 from .qommon.templatetags.qommon import parse_datetime
 from .qommon.storage import (Or, Equal, NotEqual)
 
+from .carddef import CardDef
 from .formdef import FormDef
 
 
@@ -889,3 +890,33 @@ class LazyFormDefOptions(LazyFormDataVar):
             field.id = field.varname or field.id
         data = self._formdef.workflow_options
         super(LazyFormDefOptions, self).__init__(fields, data)
+
+
+class CardsSource:
+    @classmethod
+    def get_substitution_variables(cls):
+        return {'cards': cls()}
+
+    def inspect_keys(self):
+        return []
+
+    def __getattr__(self, attr):
+        try:
+            return LazyFormDef(CardDef.get_by_urlname(attr))
+        except KeyError:
+            raise AttributeError(attr)
+
+
+class FormsSource:
+    @classmethod
+    def get_substitution_variables(cls):
+        return {'forms': cls()}
+
+    def inspect_keys(self):
+        return []
+
+    def __getattr__(self, attr):
+        try:
+            return LazyFormDef(FormDef.get_by_urlname(attr))
+        except KeyError:
+            raise AttributeError(attr)
-- 
2.27.0

