better export in grid, thanks Niphlod

This commit is contained in:
mdipierro
2012-07-19 16:25:22 -05:00
parent 498588d53d
commit fe7adb4575
2 changed files with 135 additions and 59 deletions
+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 - 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 http import HTTP
from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR from html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG, SCRIPT
from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON, IMG from html import FORM, INPUT, LABEL, OPTION, SELECT, BUTTON
from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE, SCRIPT from html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE
from html import URL, truncate_string 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 storage import Storage
from utils import md5_hash from utils import md5_hash
from validators import IS_EMPTY_OR, IS_NOT_EMPTY, IS_LIST_OF, IS_DATE, \ 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]) ondelete(table,request.args[-1])
ret = db(table[table._id.name]==request.args[-1]).delete() ret = db(table[table._id.name]==request.args[-1]).delete()
return ret return ret
elif csv and len(request.args)>0 and request.args[-1]=='csv':
if request.vars.keywords: #elif csv and len(request.args)>0 and request.args[-1]=='csv':
try: # if request.vars.keywords:
dbset=dbset(SQLFORM.build_query( # try:
fields, # dbset=dbset(SQLFORM.build_query(
request.vars.get('keywords',''))) # fields,
except: # request.vars.get('keywords','')))
raise HTTP(400) # except:
check_authorization() # raise HTTP(400)
response.headers['Content-Type'] = 'text/csv' # check_authorization()
response.headers['Content-Disposition'] = \ # response.headers['Content-Type'] = 'text/csv'
'attachment;filename=rows.csv;' # response.headers['Content-Disposition'] = \
raise HTTP(200,str(dbset.select()), # 'attachment;filename=rows.csv;'
**{'Content-Type':'text/csv', # raise HTTP(200,str(dbset.select()),
'Content-Disposition':'attachment;filename=rows.csv;'}) # **{'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, csv=ExporterCsv,
html=ExporterHtml, html=ExporterHtml,
tsv_with_hidden_cols=(ExporterTsv, 'tsv with hidden cols'), tsv_with_hidden_cols=(ExporterTsv, 'tsv (Excel compatible), hidden cols'),
tsv=ExporterTsv) tsv=(ExporterTsv, 'tsv (Excel compatible)')
)
if not exportclasses is None: if not exportclasses is None:
exportManager.update(exportclasses) exportManager.update(exportclasses)
@@ -1744,11 +1750,15 @@ class SQLFORM(FORM):
request.vars.get('keywords',''))) request.vars.get('keywords','')))
except: except:
raise HTTP(400) raise HTTP(400)
check_authorization()
rows = dbset.select() rows = dbset.select()
else: else:
rows = dbset.select(left=left,orderby=orderby,*columns) 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 not export_type is None:
if exportManager.has_key(export_type): if exportManager.has_key(export_type):
value = exportManager[export_type] value = exportManager[export_type]
@@ -1825,12 +1835,12 @@ class SQLFORM(FORM):
buttontext='Add', buttontext='Add',
buttonurl=url(args=['new',tablename]))) buttonurl=url(args=['new',tablename])))
if csv and nrows: if csv and nrows:
search_actions.append(gridbutton( #search_actions.append(gridbutton(
buttonclass='buttonexport', # buttonclass='buttonexport',
buttontext='Export', # buttontext='Export',
trap = False, # trap = False,
buttonurl=url(args=['csv'], # buttonurl=url(args=['csv'],
vars=dict(keywords=request.vars.keywords or '')))) # vars=dict(keywords=request.vars.keywords or ''))))
#================================================================ #================================================================
options =[] options =[]
@@ -1840,11 +1850,16 @@ class SQLFORM(FORM):
else: else:
label = k label = k
options.append(OPTION(T(label),_value=k)) options.append(OPTION(T(label),_value=k))
f = FORM(BUTTON(SPAN(_class="icon downarrow icon-download"), ##FIXME ?
"Export", _type="submit", _class="btn button"), 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"), SELECT(options, _name="export_type"),
INPUT(_type="hidden", _name="order", INPUT(_type="hidden", _name="order",
_value=request.vars.order), _value=request.vars.order),
INPUT(_type="hidden", _name="_signature",
_value=mysignature),
INPUT(_type="hidden", _name="keywords", INPUT(_type="hidden", _name="keywords",
_value=request.vars.keywords or ''), _value=request.vars.keywords or ''),
_method="GET", _action=url(args=['export'])) _method="GET", _action=url(args=['export']))
@@ -2465,21 +2480,82 @@ class ExportClass(object):
def __init__(self, rows): def __init__(self, rows):
self.rows = 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): def export(self):
raise NotImplementedError raise NotImplementedError
class ExporterTsv(ExportClass): class ExporterTsv(ExportClass):
file_ext = "tsv"
file_ext = "csv"
content_type = "text/tab-separated-values" content_type = "text/tab-separated-values"
def __init__(self, rows): def __init__(self, rows):
ExportClass.__init__(self, rows) ExportClass.__init__(self, rows)
def export(self): 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): class ExporterCsv(ExportClass):
file_ext = "csv" file_ext = "csv"