better export in grid, thanks Niphlod

This commit is contained in:
mdipierro committed 2012-07-19 16:25:22 -05:00
1 parent f1337d563e
commit f01b61c4c9
2 files changed
+114 -38

No files matched your search

+1 -1
View File
@@ -1 +1 @@
Version 2.00.0 (2012-07-18 21:46:56) dev
Version 2.00.0 (2012-07-19 16:25:16) dev
+113 -37
View File
@@ -13,13 +13,17 @@ Holds:
- form_factory: provides a SQLFORM for an non-db backed table
"""
try:
from urlparse import parse_qs as psq
except ImportError:
from cgi import parse_qs as psq
from http import HTTP
from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR
from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON, IMG
from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE, SCRIPT
from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG, SCRIPT
from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON
from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE
from html import URL, truncate_string
from dal import DAL, Field, Table, Row, CALLABLETYPES, smart_query
from dal import DAL, Field, Table, Row, CALLABLETYPES, smart_query, \
bar_encode, regex_table_field, Reference
from storage import Storage
from utils import md5_hash
from validators import IS_EMPTY_OR, IS_NOT_EMPTY, IS_LIST_OF, IS_DATE, \
@@ -1694,29 +1698,31 @@ class SQLFORM(FORM):
ondelete(table,request.args[-1])
ret = db(table[table._id.name]==request.args[-1]).delete()
return ret
elif csv and len(request.args)>0 and request.args[-1]=='csv':
if request.vars.keywords:
try:
dbset=dbset(SQLFORM.build_query(
fields,
request.vars.get('keywords','')))
except:
raise HTTP(400)
check_authorization()
response.headers['Content-Type'] = 'text/csv'
response.headers['Content-Disposition'] = \
'attachment;filename=rows.csv;'
raise HTTP(200,str(dbset.select()),
**{'Content-Type':'text/csv',
'Content-Disposition':'attachment;filename=rows.csv;'})
#elif csv and len(request.args)>0 and request.args[-1]=='csv':
# if request.vars.keywords:
# try:
# dbset=dbset(SQLFORM.build_query(
# fields,
# request.vars.get('keywords','')))
# except:
# raise HTTP(400)
# check_authorization()
# response.headers['Content-Type'] = 'text/csv'
# response.headers['Content-Disposition'] = \
# 'attachment;filename=rows.csv;'
# raise HTTP(200,str(dbset.select()),
# **{'Content-Type':'text/csv',
# 'Content-Disposition':'attachment;filename=rows.csv;'})
#==============================================================================
exportManager = dict(csv_with_hidden_cols=(ExporterCsv,'csv with hidden cols'),
exportManager = dict(csv_with_hidden_cols=(ExporterCsv,'csv, hidden cols'),
csv=ExporterCsv,
html=ExporterHtml,
tsv_with_hidden_cols=(ExporterTsv, 'tsv with hidden cols'),
tsv=ExporterTsv)
tsv_with_hidden_cols=(ExporterTsv, 'tsv (Excel compatible), hidden cols'),
tsv=(ExporterTsv, 'tsv (Excel compatible)')
)
if not exportclasses is None:
exportManager.update(exportclasses)
@@ -1744,11 +1750,15 @@ class SQLFORM(FORM):
request.vars.get('keywords','')))
except:
raise HTTP(400)
check_authorization()
rows = dbset.select()
else:
rows = dbset.select(left=left,orderby=orderby,*columns)
##FIXME ?
#check_authorization()
if user_signature:
if not URL.verify(request,user_signature=user_signature,hash_vars=False):
session.flash = T('not authorized')
redirect(referrer)
if not export_type is None:
if exportManager.has_key(export_type):
value = exportManager[export_type]
@@ -1825,12 +1835,12 @@ class SQLFORM(FORM):
buttontext='Add',
buttonurl=url(args=['new',tablename])))
if csv and nrows:
search_actions.append(gridbutton(
buttonclass='buttonexport',
buttontext='Export',
trap = False,
buttonurl=url(args=['csv'],
vars=dict(keywords=request.vars.keywords or ''))))
#search_actions.append(gridbutton(
# buttonclass='buttonexport',
# buttontext='Export',
# trap = False,
# buttonurl=url(args=['csv'],
# vars=dict(keywords=request.vars.keywords or ''))))
#================================================================
options =[]
@@ -1840,11 +1850,16 @@ class SQLFORM(FORM):
else:
label = k
options.append(OPTION(T(label),_value=k))
f = FORM(BUTTON(SPAN(_class="icon downarrow icon-download"),
"Export", _type="submit", _class="btn button"),
##FIXME ?
mysignature = url(args=['export']).split('?', 1)
mysignature = psq(mysignature[-1]).get('_signature', [None])[-1]
f = FORM(BUTTON(SPAN(_class=ui.get('buttonexport')),
"Export", _type="submit", _class=ui.get('button')),
SELECT(options, _name="export_type"),
INPUT(_type="hidden", _name="order",
_value=request.vars.order),
INPUT(_type="hidden", _name="_signature",
_value=mysignature),
INPUT(_type="hidden", _name="keywords",
_value=request.vars.keywords or ''),
_method="GET", _action=url(args=['export']))
@@ -2465,21 +2480,82 @@ class ExportClass(object):
def __init__(self, rows):
self.rows = rows
def represented(self):
def none_exception(value):
"""
returns a cleaned up value that can be used for csv export:
- unicode text is encoded as such
- None values are replaced with the given representation (default <NULL>)
"""
if value is None:
return '<NULL>'
elif isinstance(value, unicode):
return value.encode('utf8')
elif isinstance(value,Reference):
return int(value)
elif hasattr(value, 'isoformat'):
return value.isoformat()[:19].replace('T', ' ')
elif isinstance(value, (list,tuple)): # for type='list:..'
return bar_encode(value)
return value
represented = []
for record in self.rows:
row = []
for col in self.rows.colnames:
if not regex_table_field.match(col):
row.append(record._extra[col])
else:
(t, f) = col.split('.')
field = self.rows.db[t][f]
if isinstance(record.get(t, None), (Row,dict)):
value = record[t][f]
else:
value = record[f]
if field.type=='blob' and not value is None:
value = ''
elif field.represent:
value = field.represent(value, record)
row.append(none_exception(value))
represented.append(row)
return represented
def export(self):
raise NotImplementedError
class ExporterTsv(ExportClass):
file_ext = "tsv"
file_ext = "csv"
content_type = "text/tab-separated-values"
def __init__(self, rows):
ExportClass.__init__(self, rows)
def export(self):
out = cStringIO.StringIO()
self.rows.export_to_csv_file(out, delimiter='\t', represent=True)
return str(out.getvalue())
out = cStringIO.StringIO()
final = cStringIO.StringIO()
import csv
writer = csv.writer(out, delimiter='\t')
import codecs
final.write(codecs.BOM_UTF16)
colnames = [a.split('.') for a in self.rows.colnames]
writer.writerow([unicode(col).encode("utf8") for col in self.rows.colnames])
data = out.getvalue().decode("utf8")
data = data.encode("utf-16")
data = data[2:]
final.write(data)
out.truncate(0)
records = self.represented()
for row in records:
writer.writerow([str(col).decode('utf8').encode("utf-8") for col in row])
data = out.getvalue().decode("utf8")
data = data.encode("utf-16")
data = data[2:]
final.write(data)
out.truncate(0)
return str(final.getvalue())
class ExporterCsv(ExportClass):
file_ext = "csv"