backoffice: add possibility to display linked card fields as columns (#40036)
This commit is contained in:
parent
44c8a61a9f
commit
0d0a5ad5ee
|
@ -126,6 +126,7 @@ def create_environment(pub, set_receiver=True):
|
|||
Workflow.wipe()
|
||||
Category.wipe()
|
||||
FormDef.wipe()
|
||||
CardDef.wipe()
|
||||
pub.custom_view_class.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
|
@ -646,6 +647,86 @@ def test_backoffice_image_column(pub):
|
|||
assert 'download?f=4&thumbnail=1' not in resp.text
|
||||
|
||||
|
||||
def test_backoffice_card_field_columns(pub):
|
||||
user = create_superuser(pub)
|
||||
create_environment(pub)
|
||||
|
||||
datasource = {
|
||||
'type': 'formula',
|
||||
'value': repr([('A', 'aa'), ('B', 'bb'), ('C', 'cc')])
|
||||
}
|
||||
|
||||
CardDef.wipe()
|
||||
carddef = CardDef()
|
||||
carddef.name = 'foo'
|
||||
carddef.fields = [
|
||||
fields.CommentField(id='0', label='...', type='comment'),
|
||||
fields.StringField(id='1', label='Test', type='string', varname='foo'),
|
||||
fields.DateField(id='2', label='Date', type='date'),
|
||||
fields.BoolField(id='3', label='Bool', type='bool'),
|
||||
fields.ItemField(id='4', label='Item', type='item', data_source=datasource),
|
||||
]
|
||||
carddef.backoffice_submission_roles = user.roles
|
||||
carddef.workflow_roles = {'_editor': user.roles[0]}
|
||||
carddef.digest_template = 'card {{form_var_foo}}'
|
||||
carddef.store()
|
||||
carddef.data_class().wipe()
|
||||
|
||||
card = carddef.data_class()()
|
||||
card.data = {
|
||||
'1': 'plop',
|
||||
'2': time.strptime('2020-04-24', '%Y-%m-%d'),
|
||||
'3': True,
|
||||
'4': 'A',
|
||||
'4_display': 'aa',
|
||||
}
|
||||
card.store()
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
formdef.geolocations = {'base': 'Geolocation'}
|
||||
formdef.fields.append(
|
||||
fields.ItemField(id='4', label='card field', type='item',
|
||||
data_source={'type': 'carddef:foo', 'value': ''}))
|
||||
formdef.store()
|
||||
|
||||
for formdata in formdef.data_class().select(lambda x: x.status == 'wf-new'):
|
||||
formdata.data['4'] = str(card.id)
|
||||
formdata.data['4_display'] = formdef.fields[-1].store_display_value(formdata.data, '4')
|
||||
formdata.data['4_structured'] = formdef.fields[-1].store_structured_value(formdata.data, '4')
|
||||
formdata.geolocations = {'base': {'lat': 48.83, 'lon': 2.32}}
|
||||
formdata.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/management/form-title/')
|
||||
assert resp.text.count('</th>') == 8 # six columns
|
||||
if not pub.is_using_postgresql():
|
||||
# no support for relation columns unless using SQL
|
||||
assert '4$1' not in resp.forms['listing-settings'].fields
|
||||
return
|
||||
assert '4$0' not in resp.forms['listing-settings'].fields
|
||||
resp.forms['listing-settings']['4$1'].checked = True
|
||||
resp.forms['listing-settings']['4$2'].checked = True
|
||||
resp.forms['listing-settings']['4$3'].checked = True
|
||||
resp.forms['listing-settings']['4$4'].checked = True
|
||||
resp = resp.forms['listing-settings'].submit()
|
||||
assert resp.text.count('</th>') == 12
|
||||
assert resp.text.count('data-link') == 17 # 17 rows
|
||||
assert resp.text.count('<td>plop</td>') == 17
|
||||
assert resp.text.count('<td>2020-04-24</td>') == 17
|
||||
assert resp.text.count('<td>Yes</td>') == 17
|
||||
assert resp.text.count('<td>aa</td>') == 17
|
||||
|
||||
resp_csv = resp.click('Export as CSV File')
|
||||
assert resp_csv.text.splitlines()[1].endswith(',plop,2020-04-24,Yes,aa')
|
||||
|
||||
resp_ods = resp.click('Export a Spreadsheet')
|
||||
|
||||
resp_map = resp.click('Plot on a Map')
|
||||
geojson_url = re.findall(r'data-geojson-url="(.*?)"', resp_map.text)[0]
|
||||
resp_geojson = app.get(geojson_url)
|
||||
assert {'varname': None, 'label': 'card field - Test', 'value': 'plop', 'html_value': 'plop'} in resp_geojson.json['features'][0]['properties']['display_fields']
|
||||
|
||||
|
||||
def test_backoffice_filter(pub):
|
||||
create_superuser(pub)
|
||||
create_environment(pub)
|
||||
|
|
|
@ -1190,7 +1190,7 @@ class FormPage(Directory):
|
|||
default_filters = self.get_default_filters(mode)
|
||||
|
||||
filter_fields = []
|
||||
for field in fake_fields + self.get_formdef_fields():
|
||||
for field in fake_fields + list(self.get_formdef_fields()):
|
||||
field.enabled = False
|
||||
if field.type not in self.get_filterable_field_types() + ['status']:
|
||||
continue
|
||||
|
@ -1419,14 +1419,29 @@ class FormPage(Directory):
|
|||
return field_ids.index(x.id)
|
||||
return 9999
|
||||
|
||||
seen_parents = set()
|
||||
for field in sorted(self.get_formdef_fields(), key=get_column_position):
|
||||
if not hasattr(field, str('get_view_value')):
|
||||
continue
|
||||
r += htmltext('<li><span class="handle">⣿</span><label><input type="checkbox" name="%s"') % field.id
|
||||
classnames = ''
|
||||
attrs = ''
|
||||
if isinstance(field, RelatedField):
|
||||
classnames = 'related-field'
|
||||
if field.parent_field.id in seen_parents:
|
||||
classnames += ' collapsed'
|
||||
attrs = 'data-relation-attr="%s"' % field.parent_field.id
|
||||
elif getattr(field, 'has_relations', False):
|
||||
classnames = 'has-relations-field'
|
||||
attrs = 'data-field-id="%s"' % field.id
|
||||
seen_parents.add(field.id)
|
||||
r += htmltext('<li class="%s" %s><span class="handle">⣿</span>' % (classnames, attrs))
|
||||
r += htmltext('<label><input type="checkbox" name="%s"') % field.id
|
||||
if field.id in field_ids:
|
||||
r += htmltext(' checked="checked"')
|
||||
r += htmltext('/>')
|
||||
r += htmltext('%s</label>') % misc.ellipsize(field.label, 70)
|
||||
if getattr(field, 'has_relations', False):
|
||||
r += htmltext('<button class="expand-relations"></button>')
|
||||
r += htmltext('</li>')
|
||||
column_order.append(str(field.id))
|
||||
r += htmltext('</ul>')
|
||||
|
@ -1515,20 +1530,34 @@ class FormPage(Directory):
|
|||
return redirect('..')
|
||||
|
||||
def get_formdef_fields(self):
|
||||
fields = []
|
||||
fields.append(FakeField('id', 'id', _('Number')))
|
||||
yield FakeField('id', 'id', _('Number'))
|
||||
if get_publisher().get_site_option('welco_url', 'variables'):
|
||||
fields.append(FakeField('submission_channel', 'submission_channel', _('Channel')))
|
||||
yield FakeField('submission_channel', 'submission_channel', _('Channel'))
|
||||
if self.formdef.backoffice_submission_roles:
|
||||
fields.append(FakeField('submission_agent', 'submission_agent', _('Submission By')))
|
||||
fields.append(FakeField('time', 'time', _('Created')))
|
||||
fields.append(FakeField('last_update_time', 'last_update_time', _('Last Modified')))
|
||||
fields.append(FakeField('user-label', 'user-label', _('User Label')))
|
||||
fields.extend(self.formdef.get_all_fields())
|
||||
fields.append(FakeField('status', 'status', _('Status')))
|
||||
fields.append(FakeField('anonymised', 'anonymised', _('Anonymised')))
|
||||
yield FakeField('submission_agent', 'submission_agent', _('Submission By'))
|
||||
yield FakeField('time', 'time', _('Created'))
|
||||
yield FakeField('last_update_time', 'last_update_time', _('Last Modified'))
|
||||
yield FakeField('user-label', 'user-label', _('User Label'))
|
||||
for field in self.formdef.get_all_fields():
|
||||
yield field
|
||||
if not get_publisher().is_using_postgresql():
|
||||
continue
|
||||
if not (field.type == 'item' and
|
||||
field.data_source and
|
||||
field.data_source.get('type', '').startswith('carddef:')):
|
||||
continue
|
||||
try:
|
||||
carddef = CardDef.get_by_urlname(field.data_source['type'][8:])
|
||||
except KeyError:
|
||||
continue
|
||||
for card_field in carddef.get_all_fields():
|
||||
if not hasattr(card_field, 'get_view_value'):
|
||||
continue
|
||||
field.has_relations = True
|
||||
yield RelatedField(carddef, card_field, field)
|
||||
|
||||
return fields
|
||||
yield FakeField('status', 'status', _('Status'))
|
||||
yield FakeField('anonymised', 'anonymised', _('Anonymised'))
|
||||
|
||||
def get_default_columns(self):
|
||||
if self.view:
|
||||
|
@ -1596,7 +1625,7 @@ class FormPage(Directory):
|
|||
filters_dict.update(self.view.get_filters_dict())
|
||||
filters_dict.update(get_request().form)
|
||||
|
||||
for filter_field in fake_fields + self.get_formdef_fields():
|
||||
for filter_field in fake_fields + list(self.get_formdef_fields()):
|
||||
if filter_field.type not in self.get_filterable_field_types():
|
||||
continue
|
||||
|
||||
|
@ -1913,7 +1942,7 @@ class FormPage(Directory):
|
|||
csv_output.writerow(self.formpage.csv_tuple_heading(self.fields))
|
||||
|
||||
items, total_count = FormDefUI(self.formdef).get_listing_items(
|
||||
self.selected_filter, user=user, query=query,
|
||||
fields, self.selected_filter, user=user, query=query,
|
||||
criterias=criterias)
|
||||
|
||||
for filled in items:
|
||||
|
@ -2015,7 +2044,7 @@ class FormPage(Directory):
|
|||
ws.write(0, i, f)
|
||||
|
||||
items, total_count = FormDefUI(self.formdef).get_listing_items(
|
||||
self.selected_filter, user=user, query=query,
|
||||
fields, self.selected_filter, user=user, query=query,
|
||||
criterias=criterias)
|
||||
|
||||
for i, filled in enumerate(items):
|
||||
|
@ -2080,7 +2109,7 @@ class FormPage(Directory):
|
|||
ws.write(0, i, f)
|
||||
|
||||
items, total_count = FormDefUI(self.formdef).get_listing_items(
|
||||
self.selected_filter, user=user, query=query,
|
||||
fields, self.selected_filter, user=user, query=query,
|
||||
criterias=criterias)
|
||||
|
||||
for i, formdata in enumerate(items):
|
||||
|
@ -2136,7 +2165,7 @@ class FormPage(Directory):
|
|||
if 'limit' in get_request().form:
|
||||
limit = misc.get_int_or_400(get_request().form['limit'])
|
||||
items, total_count = FormDefUI(self.formdef).get_listing_items(
|
||||
selected_filter, user=user, query=query, criterias=criterias,
|
||||
None, selected_filter, user=user, query=query, criterias=criterias,
|
||||
order_by=order_by, anonymise=anonymise, offset=offset, limit=limit)
|
||||
if get_publisher().is_using_postgresql():
|
||||
self.formdef.data_class().load_all_evolutions(items)
|
||||
|
@ -2179,7 +2208,7 @@ class FormPage(Directory):
|
|||
query = get_request().form.get('q')
|
||||
|
||||
items, total_count = FormDefUI(self.formdef).get_listing_items(
|
||||
selected_filter, user=user, query=query, criterias=criterias)
|
||||
fields, selected_filter, user=user, query=query, criterias=criterias)
|
||||
|
||||
# only consider first key for now
|
||||
geoloc_key = list(self.formdef.geolocations.keys())[0]
|
||||
|
@ -2232,7 +2261,7 @@ class FormPage(Directory):
|
|||
raise errors.TraversalError()
|
||||
|
||||
formdatas, total_count = FormDefUI(formdef).get_listing_items(
|
||||
selected_filter, user=user, query=query, criterias=criterias)
|
||||
fields, selected_filter, user=user, query=query, criterias=criterias)
|
||||
|
||||
cal = vobject.iCalendar()
|
||||
cal.add('prodid').value = '-//Entr\'ouvert//NON SGML Publik'
|
||||
|
@ -3132,6 +3161,44 @@ class FakeField(object):
|
|||
return [element]
|
||||
|
||||
|
||||
class RelatedField:
|
||||
is_related_field = True
|
||||
type = 'related-field'
|
||||
store_display_value = None
|
||||
varname = None
|
||||
|
||||
def __init__(self, carddef, field, parent_field):
|
||||
self.carddef = carddef
|
||||
self.carddef_field = field
|
||||
self.parent_field = parent_field
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return '%s$%s' % (self.parent_field.id, self.carddef_field.id)
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return '%s - %s' % (self.parent_field.label, self.carddef_field.label)
|
||||
|
||||
def get_view_value(self, value, **kwargs):
|
||||
if value is None:
|
||||
return ''
|
||||
if isinstance(value, bool):
|
||||
return _('Yes') if value else _('No')
|
||||
if isinstance(value, datetime.date):
|
||||
return misc.strftime(misc.date_format(), value)
|
||||
return value
|
||||
|
||||
def get_view_short_value(self, value, max_len=30, **kwargs):
|
||||
return self.get_view_value(value)
|
||||
|
||||
def get_csv_heading(self):
|
||||
return [self.label]
|
||||
|
||||
def get_csv_value(self, value, **kwargs):
|
||||
return [self.get_view_value(value)]
|
||||
|
||||
|
||||
def do_graphs_section(period_start=None, period_end=None, criterias=None):
|
||||
from wcs import sql
|
||||
r = TemplateIO(html=True)
|
||||
|
|
|
@ -47,7 +47,7 @@ class FormDefUI(object):
|
|||
if using_postgresql:
|
||||
criterias.append(Null('anonymised'))
|
||||
items, total_count = self.get_listing_items(
|
||||
selected_filter, offset, limit, query, order_by,
|
||||
fields, selected_filter, offset, limit, query, order_by,
|
||||
criterias=criterias)
|
||||
if (offset > 0) or (total_count > limit > 0):
|
||||
partial_display = True
|
||||
|
@ -102,6 +102,8 @@ class FormDefUI(object):
|
|||
field_sort_key = 'receipt_time'
|
||||
elif f.id in ('user-label', 'submission_agent'):
|
||||
field_sort_key = None
|
||||
elif hasattr(f, 'column_id'):
|
||||
field_sort_key = None
|
||||
else:
|
||||
field_sort_key = 'f%s' % f.id
|
||||
|
||||
|
@ -178,7 +180,7 @@ class FormDefUI(object):
|
|||
|
||||
return item_ids
|
||||
|
||||
def get_listing_items(self, selected_filter='all', offset=None,
|
||||
def get_listing_items(self, fields=None, selected_filter='all', offset=None,
|
||||
limit=None, query=None, order_by=None, user=None, criterias=None, anonymise=False):
|
||||
user = user or get_request().user
|
||||
formdata_class = self.formdef.data_class()
|
||||
|
@ -206,15 +208,18 @@ class FormDefUI(object):
|
|||
if not offset:
|
||||
offset = 0
|
||||
|
||||
kwargs = {}
|
||||
if get_publisher().is_using_postgresql():
|
||||
kwargs['fields'] = fields
|
||||
|
||||
if limit:
|
||||
items = formdata_class.get_ids(item_ids[offset:offset+limit],
|
||||
keep_order=True)
|
||||
keep_order=True, **kwargs)
|
||||
else:
|
||||
items = formdata_class.get_ids(item_ids, keep_order=True)
|
||||
items = formdata_class.get_ids(item_ids, keep_order=True, **kwargs)
|
||||
|
||||
return (items, total_count)
|
||||
|
||||
|
||||
def tbody(self, fields=None, items=None, url_action=None, include_checkboxes=False):
|
||||
r = TemplateIO(html=True)
|
||||
if url_action:
|
||||
|
|
|
@ -1121,6 +1121,27 @@ ul.columns-filter li label {
|
|||
padding-left: 2em;
|
||||
}
|
||||
|
||||
ul.columns-filter li.collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul.columns-filter button.expand-relations {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul.columns-filter button.expand-relations::before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f107"; /* angle-down */
|
||||
}
|
||||
|
||||
ul.columns-filter button.expand-relations.opened::before {
|
||||
content: "\f106"; // angle-up
|
||||
}
|
||||
|
||||
ul.multipage li {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
|
|
@ -213,6 +213,17 @@ $(function() {
|
|||
var dialog = $('<form>');
|
||||
var $dialog_filter = $('#columns-filter').clone().attr('id', null);
|
||||
$dialog_filter.appendTo(dialog);
|
||||
$dialog_filter.find('button.expand-relations').each(function(elem, i) {
|
||||
$(this).removeClass('opened');
|
||||
var field_id = $(this).parents('li.has-relations-field').data('field-id');
|
||||
$(this).parents('li').find('~ li[data-relation-attr=' + field_id + ']').addClass('collapsed');
|
||||
});
|
||||
$dialog_filter.find('button.expand-relations').on('click', function() {
|
||||
$(this).toggleClass('opened');
|
||||
var field_id = $(this).parents('li.has-relations-field').data('field-id');
|
||||
$(this).parents('li').find('~ li[data-relation-attr=' + field_id + ']').toggleClass('collapsed');
|
||||
return false;
|
||||
});
|
||||
$dialog_filter.sortable({handle: '.handle'})
|
||||
$(dialog).dialog({
|
||||
closeText: WCS_I18N.close,
|
||||
|
|
|
@ -405,7 +405,7 @@ class StorableObject(object):
|
|||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def get_ids(cls, ids, ignore_errors=False, keep_order=False):
|
||||
def get_ids(cls, ids, ignore_errors=False, **kwargs):
|
||||
objects = []
|
||||
for x in ids:
|
||||
obj = cls.get(x, ignore_errors=ignore_errors)
|
||||
|
|
64
wcs/sql.py
64
wcs/sql.py
|
@ -1139,19 +1139,45 @@ class SqlMixin(object):
|
|||
|
||||
@classmethod
|
||||
@guard_postgres
|
||||
def get_ids(cls, ids, ignore_errors=False, keep_order=False):
|
||||
def get_ids(cls, ids, ignore_errors=False, keep_order=False, fields=None):
|
||||
if not ids:
|
||||
return []
|
||||
tables = [cls._table_name]
|
||||
columns = ['%s.%s' % (cls._table_name, column_name) for column_name in
|
||||
[x[0] for x in cls._table_static_fields] + cls.get_data_fields()]
|
||||
extra_fields = []
|
||||
if fields:
|
||||
# look for relations
|
||||
for field in fields:
|
||||
if not getattr(field, 'is_related_field', False):
|
||||
continue
|
||||
carddef_dataclass = field.carddef.data_class()
|
||||
carddef_table_alias = 't%s' % id(field.carddef)
|
||||
carddef_table_decl = 'LEFT JOIN %s AS %s ON (CAST(%s.%s AS INTEGER) = %s.id)' % (
|
||||
carddef_dataclass._table_name,
|
||||
carddef_table_alias,
|
||||
cls._table_name,
|
||||
get_field_id(field.parent_field),
|
||||
carddef_table_alias)
|
||||
if carddef_table_decl not in tables:
|
||||
tables.append(carddef_table_decl)
|
||||
|
||||
column_field_id = get_field_id(field.carddef_field)
|
||||
if field.carddef_field.store_display_value:
|
||||
column_field_id += '_display'
|
||||
columns.append('%s.%s' % (carddef_table_alias, column_field_id))
|
||||
extra_fields.append(field.id)
|
||||
|
||||
conn, cur = get_connection_and_cursor()
|
||||
sql_statement = '''SELECT %s
|
||||
FROM %s
|
||||
WHERE id IN (%s)''' % (
|
||||
', '.join([x[0] for x in cls._table_static_fields]
|
||||
+ cls.get_data_fields()),
|
||||
WHERE %s.id IN (%s)''' % (
|
||||
', '.join(columns),
|
||||
' '.join(tables),
|
||||
cls._table_name,
|
||||
','.join([str(x) for x in ids]))
|
||||
cur.execute(sql_statement)
|
||||
objects = cls.get_objects(cur)
|
||||
objects = cls.get_objects(cur, extra_fields=extra_fields)
|
||||
conn.commit()
|
||||
cur.close()
|
||||
if ignore_errors:
|
||||
|
@ -1164,16 +1190,19 @@ class SqlMixin(object):
|
|||
return list(objects)
|
||||
|
||||
@classmethod
|
||||
def get_objects_iterator(cls, cur, ignore_errors=False):
|
||||
def get_objects_iterator(cls, cur, ignore_errors=False, extra_fields=None):
|
||||
while True:
|
||||
row = cur.fetchone()
|
||||
if row is None:
|
||||
break
|
||||
yield cls._row2ob(row)
|
||||
yield cls._row2ob(row, extra_fields=extra_fields)
|
||||
|
||||
@classmethod
|
||||
def get_objects(cls, cur, ignore_errors=False, iterator=False):
|
||||
generator = cls.get_objects_iterator(cur=cur, ignore_errors=ignore_errors)
|
||||
def get_objects(cls, cur, ignore_errors=False, iterator=False, extra_fields=None):
|
||||
generator = cls.get_objects_iterator(
|
||||
cur=cur,
|
||||
ignore_errors=ignore_errors,
|
||||
extra_fields=extra_fields)
|
||||
if iterator:
|
||||
return generator
|
||||
return list(generator)
|
||||
|
@ -1667,7 +1696,7 @@ class SqlDataMixin(SqlMixin):
|
|||
cur.close()
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, extra_fields=None):
|
||||
o = cls()
|
||||
for static_field, value in zip(cls._table_static_fields,
|
||||
tuple(row[:len(cls._table_static_fields)])):
|
||||
|
@ -1691,6 +1720,11 @@ class SqlDataMixin(SqlMixin):
|
|||
'lat': float(m.group(2))}
|
||||
|
||||
o.data = cls._row2obdata(row, cls._formdef)
|
||||
if extra_fields:
|
||||
# extra fields are tuck at the end
|
||||
for i, field_id in enumerate(reversed(extra_fields)):
|
||||
o.data[field_id] = row[-(i + 1)]
|
||||
pass
|
||||
del o._last_update_time
|
||||
return o
|
||||
|
||||
|
@ -1942,7 +1976,7 @@ class SqlUser(SqlMixin, wcs.users.User):
|
|||
cur.close()
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
o = cls()
|
||||
(o.id, o.name, o.email, o.roles, o.is_admin, o.anonymous,
|
||||
o.name_identifiers, o.verified_fields, o.lasso_dump,
|
||||
|
@ -2086,7 +2120,7 @@ class Session(SqlMixin, wcs.sessions.BasicSession):
|
|||
cur.close()
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
o = cls.__new__(cls)
|
||||
cls.id = str_encode(row[0])
|
||||
session_data = pickle_loads(row[1])
|
||||
|
@ -2191,7 +2225,7 @@ class TrackingCode(SqlMixin, wcs.tracking_code.TrackingCode):
|
|||
cur.close()
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
o = cls()
|
||||
(o.id, o.formdef_id, o.formdata_id) = [str_encode(x) for x in tuple(row[:3])]
|
||||
return o
|
||||
|
@ -2266,7 +2300,7 @@ class CustomView(SqlMixin, wcs.custom_views.CustomView):
|
|||
cur.close()
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
o = cls()
|
||||
for field, value in zip(cls._table_static_fields, tuple(row)):
|
||||
if field[1] == 'varchar':
|
||||
|
@ -2318,7 +2352,7 @@ class AnyFormData(SqlMixin):
|
|||
return super(AnyFormData, cls).get_objects(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row):
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
formdef_id = row[1]
|
||||
from wcs.formdef import FormDef
|
||||
formdef = cls._formdef_cache.setdefault(formdef_id, FormDef.get(formdef_id))
|
||||
|
|
Loading…
Reference in New Issue