api: include file info in list API (#42371)
This commit is contained in:
parent
739f2557b3
commit
07617b5f1b
|
@ -238,7 +238,8 @@ Les champs de type « Fichier » sont exportés selon le schéma suivant :
|
|||
"photo": {
|
||||
"filename": "exemple.txt",
|
||||
"content_type": "text/plain",
|
||||
"content": "Q2VjaSBuJ2VzdCBwYXMgdW4gZXhlbXBsZS4="
|
||||
"content": "Q2VjaSBuJ2VzdCBwYXMgdW4gZXhlbXBsZS4=",
|
||||
"url": "https://.../"
|
||||
}
|
||||
},
|
||||
(...)
|
||||
|
@ -333,8 +334,8 @@ l'adresse.
|
|||
</screen>
|
||||
|
||||
<p>
|
||||
À noter que pour ne pas alourdir l'export en mode <code>full=on</code>, les
|
||||
champs de type « Fichier » ne sont pas exportés.
|
||||
À noter que pour ne pas alourdir l'export en mode <code>full=on</code>, le
|
||||
contenu des champs de type « Fichier » n'est pas exporté.
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -1633,7 +1633,8 @@ def test_user_drafts(pub, local_user):
|
|||
assert resp.json['err'] == 0
|
||||
assert 'fields' in resp.json['data'][0]
|
||||
assert resp.json['data'][0]['fields']['foobar'] == 'foo@localhost'
|
||||
assert 'file' not in resp.json['data'][0]['fields'] # no file export in full lists
|
||||
assert 'url' in resp.json['data'][0]['fields']['file']
|
||||
assert 'content' not in resp.json['data'][0]['fields']['file'] # no file content in full lists
|
||||
assert resp.json['data'][0]['keywords'] == ['hello', 'world']
|
||||
|
||||
formdef.enable_tracking_codes = False
|
||||
|
@ -1724,7 +1725,8 @@ def test_api_list_formdata(pub, local_user):
|
|||
assert len(resp.json) == 30
|
||||
assert 'receipt_time' in resp.json[0]
|
||||
assert 'fields' in resp.json[0]
|
||||
assert 'file' not in resp.json[0]['fields'] # no file export in full lists
|
||||
assert 'url' in resp.json[0]['fields']['file']
|
||||
assert 'content' not in resp.json[0]['fields']['file'] # no file content in full lists
|
||||
assert 'user' in resp.json[0]
|
||||
assert 'evolution' in resp.json[0]
|
||||
assert len(resp.json[0]['evolution']) == 2
|
||||
|
|
|
@ -1127,6 +1127,9 @@ class FileField(WidgetField):
|
|||
t += htmltext('</div>')
|
||||
return t.getvalue()
|
||||
|
||||
def get_download_url(self, formdata):
|
||||
return '%sdownload?f=%s' % (formdata.get_url(), self.id)
|
||||
|
||||
def get_opendocument_node_value(self, value, formdata=None, **kwargs):
|
||||
show_link = True
|
||||
if value.has_redirect_url():
|
||||
|
@ -1134,7 +1137,7 @@ class FileField(WidgetField):
|
|||
show_link = bool(value.get_redirect_url(backoffice=is_in_backoffice))
|
||||
if show_link and formdata:
|
||||
node = ET.Element('{%s}a' % OD_NS['text'])
|
||||
node.attrib['{%s}href' % OD_NS['xlink']] = '%sdownload?f=%s' % (formdata.get_url(), self.id)
|
||||
node.attrib['{%s}href' % OD_NS['xlink']] = self.get_download_url(formdata)
|
||||
else:
|
||||
node = ET.Element('{%s}span' % OD_NS['text'])
|
||||
node.text = od_clean_text(force_text(value))
|
||||
|
@ -1143,8 +1146,10 @@ class FileField(WidgetField):
|
|||
def get_csv_value(self, value, **kwargs):
|
||||
return [str(value) if value else '']
|
||||
|
||||
def get_json_value(self, value):
|
||||
out = value.get_json_value()
|
||||
def get_json_value(self, value, formdata=None, include_file_content=True, **kwargs):
|
||||
out = value.get_json_value(include_file_content=include_file_content)
|
||||
if formdata:
|
||||
out['url'] = self.get_download_url(formdata)
|
||||
out['field_id'] = self.id
|
||||
return out
|
||||
|
||||
|
@ -1323,7 +1328,7 @@ class DateField(WidgetField):
|
|||
span.text = od_clean_text(self.get_view_value(value))
|
||||
return span
|
||||
|
||||
def get_json_value(self, value):
|
||||
def get_json_value(self, value, **kwargs):
|
||||
try:
|
||||
return strftime('%Y-%m-%d', value)
|
||||
except TypeError:
|
||||
|
@ -2406,7 +2411,7 @@ class MapField(WidgetField):
|
|||
return None
|
||||
return value
|
||||
|
||||
def get_json_value(self, value):
|
||||
def get_json_value(self, value, **kwargs):
|
||||
if not value or ';' not in value:
|
||||
return None
|
||||
lat, lon = value.split(';')
|
||||
|
|
|
@ -108,32 +108,6 @@ def flatten_dict(d):
|
|||
del d[k]
|
||||
|
||||
|
||||
def get_json_dict(fields, data, include_files=True, anonymise=False):
|
||||
new_data = {}
|
||||
for field in fields:
|
||||
if anonymise and field.anonymise:
|
||||
continue
|
||||
if not field.varname: # exports only named fields
|
||||
continue
|
||||
if not include_files and isinstance(field, FileField):
|
||||
continue
|
||||
if data is not None:
|
||||
value = data.get(field.id)
|
||||
if value and hasattr(field, 'get_json_value'):
|
||||
value = field.get_json_value(value)
|
||||
else:
|
||||
value = display_value = None
|
||||
if field.store_display_value:
|
||||
new_data[field.varname + '_raw'] = value
|
||||
new_data[field.varname] = data.get('%s_display' % field.id)
|
||||
else:
|
||||
new_data[field.varname] = value
|
||||
if field.store_structured_value:
|
||||
if data.get('%s_structured' % field.id):
|
||||
new_data[field.varname + '_structured'] = data.get('%s_structured' % field.id)
|
||||
return new_data
|
||||
|
||||
|
||||
class Evolution(object):
|
||||
who = None
|
||||
status = None
|
||||
|
@ -1018,6 +992,29 @@ class FormData(StorableObject):
|
|||
return field.get_json_value(self.data[field.id])
|
||||
return None
|
||||
|
||||
def get_json_dict(self, fields, include_files=True, anonymise=False):
|
||||
new_data = {}
|
||||
for field in fields:
|
||||
if anonymise and field.anonymise:
|
||||
continue
|
||||
if not field.varname: # exports only named fields
|
||||
continue
|
||||
if self.data is not None:
|
||||
value = self.data.get(field.id)
|
||||
if value and hasattr(field, 'get_json_value'):
|
||||
value = field.get_json_value(value, formdata=self, include_file_content=include_files)
|
||||
else:
|
||||
value = None
|
||||
if field.store_display_value:
|
||||
new_data[field.varname + '_raw'] = value
|
||||
new_data[field.varname] = self.data.get('%s_display' % field.id)
|
||||
else:
|
||||
new_data[field.varname] = value
|
||||
if field.store_structured_value:
|
||||
if self.data.get('%s_structured' % field.id):
|
||||
new_data[field.varname + '_structured'] = self.data.get('%s_structured' % field.id)
|
||||
return new_data
|
||||
|
||||
def get_json_export_dict(self, include_files=True, anonymise=False, user=None):
|
||||
data = {}
|
||||
data['id'] = str(self.id)
|
||||
|
@ -1038,7 +1035,7 @@ class FormData(StorableObject):
|
|||
if user:
|
||||
data['user'] = user.get_json_export_dict()
|
||||
|
||||
data['fields'] = get_json_dict(self.formdef.fields, self.data,
|
||||
data['fields'] = self.get_json_dict(self.formdef.fields,
|
||||
include_files=include_files, anonymise=anonymise)
|
||||
|
||||
data['workflow'] = {}
|
||||
|
@ -1049,9 +1046,9 @@ class FormData(StorableObject):
|
|||
if self.workflow_data and not anonymise:
|
||||
data['workflow']['data'] = self.workflow_data
|
||||
if self.formdef.workflow.get_backoffice_fields():
|
||||
data['workflow']['fields'] = get_json_dict(
|
||||
data['workflow']['fields'] = self.get_json_dict(
|
||||
self.formdef.workflow.get_backoffice_fields(),
|
||||
self.data, include_files=include_files, anonymise=anonymise)
|
||||
include_files=include_files, anonymise=anonymise)
|
||||
|
||||
# add a roles dictionary, with workflow functions and two special
|
||||
# entries for concerned/actions roles.
|
||||
|
|
|
@ -80,8 +80,9 @@ class PicklableUpload(Upload):
|
|||
return base64.encodestring(content)
|
||||
return b''
|
||||
|
||||
def get_json_value(self):
|
||||
return get_storage_object(getattr(self, 'storage', None)).get_json_value(self)
|
||||
def get_json_value(self, include_file_content=True):
|
||||
return get_storage_object(getattr(self, 'storage', None)).get_json_value(
|
||||
self, include_file_content=include_file_content)
|
||||
|
||||
def can_thumbnail(self):
|
||||
return get_storage_object(getattr(self, 'storage', None)).can_thumbnail(self)
|
||||
|
@ -136,12 +137,14 @@ class UploadStorage(object):
|
|||
upload.fp.seek(0)
|
||||
atomic_write(filepath, upload.fp, async_op=False)
|
||||
|
||||
def get_json_value(self, upload):
|
||||
return {
|
||||
def get_json_value(self, upload, include_file_content=True):
|
||||
value = {
|
||||
'filename': upload.base_filename,
|
||||
'content_type': upload.content_type or 'application/octet-stream',
|
||||
'content': force_text(base64.b64encode(upload.get_content())),
|
||||
}
|
||||
if include_file_content:
|
||||
value['content'] = force_text(base64.b64encode(upload.get_content()))
|
||||
return value
|
||||
|
||||
def can_thumbnail(self, upload):
|
||||
return can_thumbnail(upload.content_type)
|
||||
|
@ -217,14 +220,16 @@ class RemoteOpaqueUploadStorage(object):
|
|||
def save(self, upload):
|
||||
pass
|
||||
|
||||
def get_json_value(self, upload):
|
||||
return {
|
||||
def get_json_value(self, upload, include_file_content=True):
|
||||
value = {
|
||||
'filename': upload.base_filename,
|
||||
'content_type': upload.content_type or 'application/octet-stream',
|
||||
'content': '',
|
||||
'storage': upload.storage,
|
||||
'storage_attrs': upload.storage_attrs,
|
||||
}
|
||||
if include_file_content: # actually not possible
|
||||
value['content'] = ''
|
||||
return value
|
||||
|
||||
def can_thumbnail(self, upload):
|
||||
return False
|
||||
|
|
Loading…
Reference in New Issue