1
2
3 """ Resource Export Tools
4
5 @see: U{B{I{S3XRC}} <http://eden.sahanafoundation.org/wiki/S3XRC>}
6
7 @requires: U{B{I{gluon}} <http://web2py.com>}
8
9 @copyright: 2009-2019 (c) Sahana Software Foundation
10 @license: MIT
11
12 Permission is hereby granted, free of charge, to any person
13 obtaining a copy of this software and associated documentation
14 files (the "Software"), to deal in the Software without
15 restriction, including without limitation the rights to use,
16 copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the
18 Software is furnished to do so, subject to the following
19 conditions:
20
21 The above copyright notice and this permission notice shall be
22 included in all copies or substantial portions of the Software.
23
24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
26 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
28 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 OTHER DEALINGS IN THE SOFTWARE.
32 """
33
34 __all__ = ("S3Exporter",)
35
36 from gluon import current
37
38 from s3codec import S3Codec
39
40
42 """
43 Exporter toolkit
44 """
45
46
47 - def csv(self, resource):
48 """
49 Export resource as CSV
50
51 @param resource: the resource to export
52
53 @note: export does not include components!
54
55 @todo: implement audit
56 """
57
58 request = current.request
59 response = current.response
60
61 if response:
62 servername = request and "%s_" % request.env.server_name or ""
63 filename = "%s%s.csv" % (servername, resource.tablename)
64 from gluon.contenttype import contenttype
65 response.headers["Content-Type"] = contenttype(".csv")
66 response.headers["Content-disposition"] = "attachment; filename=%s" % filename
67
68 rows = resource.select(None, as_rows=True)
69 return str(rows)
70
71
72 - def json(self, resource,
73 start=None,
74 limit=None,
75 fields=None,
76 orderby=None,
77 represent=False,
78 tooltip=None):
79 """
80 Export a resource as JSON
81
82 @param resource: the resource to export from
83 @param start: index of the first record to export
84 @param limit: maximum number of records to export
85 @param fields: list of field selectors for fields to include in
86 the export (None for all fields)
87 @param orderby: ORDERBY expression
88 @param represent: whether values should be represented
89 @param tooltip: additional tooltip field, either a field selector
90 or an expression "f(k,v)" where f is a function
91 name that can be looked up from s3db, and k,v are
92 field selectors for the row, f will be called with
93 a list of tuples (k,v) for each row and is expected
94 to return a dict {k:tooltip} => used by
95 filterOptionsS3 to extract onhover-tooltips for
96 Ajax-update of options
97 """
98
99 if fields is None:
100
101
102
103
104
105
106 fields = resource.list_fields("json_fields", id_column=0)
107
108 if orderby is None:
109 orderby = resource.get_config("orderby", None)
110
111 tooltip_function = None
112 if tooltip:
113 if type(tooltip) is list:
114 tooltip = tooltip[-1]
115 import re
116 match = re.match(r"(\w+)\((\w+),(\w+)\)", tooltip)
117 if match:
118 function_name, kname, vname = match.groups()
119
120 tooltip_function = current.s3db.get(function_name)
121 if tooltip_function:
122 if kname not in fields:
123 fields.append(kname)
124 if vname not in fields:
125 fields.append(vname)
126 else:
127 if tooltip not in fields:
128 fields.append(tooltip)
129
130
131 _rows = resource.select(fields,
132 start=start,
133 limit=limit,
134 orderby=orderby,
135 represent=represent).rows
136
137
138 tn = "%s." % resource.tablename
139 rows = []
140 rappend = rows.append
141 for _row in _rows:
142 row = {}
143 for f in _row:
144 v = _row[f]
145 if tn in f:
146 f = f.split(tn, 1)[1]
147 row[f] = v
148 rappend(row)
149
150 if tooltip:
151 if tooltip_function:
152
153 try:
154 krfield = resource.resolve_selector(kname)
155 vrfield = resource.resolve_selector(vname)
156 except (AttributeError, SyntaxError):
157 import sys
158 current.log.error(sys.exc_info()[1])
159 else:
160
161
162 options = []
163 items = {}
164 for row in rows:
165 try:
166 k = krfield.extract(row)
167 except KeyError:
168 break
169 try:
170 v = vrfield.extract(row)
171 except KeyError:
172 break
173 items[k] = row
174 options.append((k, v))
175
176 try:
177 tooltips = tooltip_function(options)
178 except:
179 import sys
180 current.log.error(sys.exc_info()[1])
181 else:
182
183 if isinstance(tooltips, dict):
184 from s3utils import s3_unicode
185 for k, v in tooltips.items():
186 if k in items:
187 items[k]["_tooltip"] = s3_unicode(v)
188
189 else:
190
191 try:
192 tooltip_rfield = resource.resolve_selector(tooltip)
193 except (AttributeError, SyntaxError):
194 import sys
195 current.log.error(sys.exc_info()[1])
196 else:
197
198
199 from s3utils import s3_unicode
200 for row in rows:
201 try:
202 value = tooltip_rfield.extract(row)
203 except KeyError:
204 break
205 if value:
206 row["_tooltip"] = s3_unicode(value)
207
208
209 response = current.response
210 if response:
211 response.headers["Content-Type"] = "application/json"
212
213 from gluon.serializers import json as jsons
214 return jsons(rows)
215
216
217 - def pdf(self, *args, **kwargs):
221
222
223 - def pdfcard(self, *args, **kwargs):
227
228
229 - def shp(self, *args, **kwargs):
233
234
235 - def svg(self, *args, **kwargs):
239
240
241 - def xls(self, *args, **kwargs):
245
246
247