better export in grid, thanks Niphlod
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 2.00.0 (2012-07-18 21:46:56) dev
|
||||
Version 2.00.0 (2012-07-19 16:25:16) dev
|
||||
|
||||
+134
-58
@@ -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,32 +1698,34 @@ 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)
|
||||
|
||||
|
||||
if len(request.args)>0 and request.args[-1]=='export':
|
||||
export_type = request.vars.export_type
|
||||
order = request.vars.order or ''
|
||||
@@ -1734,7 +1740,7 @@ class SQLFORM(FORM):
|
||||
orderby=~db[tablename][fieldname]
|
||||
else:
|
||||
orderby=db[tablename][fieldname]
|
||||
|
||||
|
||||
table_fields = [f for f in fields if f._tablename in tablenames]
|
||||
if export_type in ('csv_with_hidden_cols','tsv_with_hidden_cols'):
|
||||
if request.vars.keywords:
|
||||
@@ -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]
|
||||
@@ -1761,12 +1771,12 @@ class SQLFORM(FORM):
|
||||
response.headers['Content-Type'] = oExp.content_type
|
||||
response.headers['Content-Disposition'] = \
|
||||
'attachment;filename='+filename+';'
|
||||
|
||||
|
||||
raise HTTP(200, oExp.export(),
|
||||
**{'Content-Type':oExp.content_type,
|
||||
'Content-Disposition':'attachment;filename='+filename+';'})
|
||||
#================================================================================
|
||||
|
||||
|
||||
elif request.vars.records and not isinstance(
|
||||
request.vars.records,list):
|
||||
request.vars.records=[request.vars.records]
|
||||
@@ -1792,7 +1802,7 @@ class SQLFORM(FORM):
|
||||
INPUT(_type='submit',_value=T('Search')),
|
||||
INPUT(_type='submit',_value=T('Clear'),
|
||||
_onclick="jQuery('#web2py_keywords').val('');"),
|
||||
mf,ms,_method="GET",_action=url)
|
||||
mf,ms,_method="GET",_action=url)
|
||||
form = search_widget and search_widget(sfields,url()) or ''
|
||||
console.append(form)
|
||||
keywords = request.vars.get('keywords','')
|
||||
@@ -1825,13 +1835,13 @@ 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 =[]
|
||||
for k,v in sorted(exportManager.items()):
|
||||
@@ -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"),
|
||||
SELECT(options, _name="export_type"),
|
||||
##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']))
|
||||
@@ -2148,21 +2163,21 @@ class SQLFORM(FORM):
|
||||
check = {}
|
||||
id_field_name = table._id.name
|
||||
for tablename,fieldname in table._referenced_by:
|
||||
if db[tablename][fieldname].readable:
|
||||
if db[tablename][fieldname].readable:
|
||||
check[tablename] = check.get(tablename,[])+[fieldname]
|
||||
for tablename in sorted(check):
|
||||
linked_fieldnames = check[tablename]
|
||||
tb = db[tablename]
|
||||
multiple_links = len(linked_fieldnames)>1
|
||||
for fieldname in linked_fieldnames:
|
||||
if linked_tables is None or tablename in linked_tables:
|
||||
for fieldname in linked_fieldnames:
|
||||
if linked_tables is None or tablename in linked_tables:
|
||||
t = T(tb._plural) if not multiple_links else T(tb._plural+'('+fieldname+')')
|
||||
args0 = tablename+'.'+fieldname
|
||||
links.append(
|
||||
lambda row,t=t,nargs=nargs,args0=args0:\
|
||||
A(SPAN(t),_class=trap_class(),_href=URL(
|
||||
args=request.args[:nargs]+[args0,row[id_field_name]])))
|
||||
|
||||
|
||||
grid=SQLFORM.grid(query,args=request.args[:nargs],links=links,
|
||||
links_in_grid=links_in_grid,
|
||||
user_signature=user_signature,**kwargs)
|
||||
@@ -2461,43 +2476,104 @@ form_factory = SQLFORM.factory # for backward compatibility, deprecated
|
||||
class ExportClass(object):
|
||||
file_ext = None
|
||||
content_type = None
|
||||
|
||||
|
||||
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())
|
||||
|
||||
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"
|
||||
content_type = "text/csv"
|
||||
|
||||
|
||||
def __init__(self, rows):
|
||||
ExportClass.__init__(self, rows)
|
||||
|
||||
|
||||
def export(self):
|
||||
return str(self.rows)
|
||||
|
||||
class ExporterHtml(ExportClass):
|
||||
file_ext = "html"
|
||||
content_type = "text/html"
|
||||
|
||||
|
||||
def __init__(self, rows):
|
||||
ExportClass.__init__(self, rows)
|
||||
|
||||
|
||||
def export(self):
|
||||
out = cStringIO.StringIO()
|
||||
out.write('<html>\n<body>\n<table>\n')
|
||||
|
||||
Reference in New Issue
Block a user