This has the same functionality as the default csv export in roundup 2.0 and newer. So it is not needed if you are running 2.0 or newer.
Also this patch was changed to add: quoting=csv.QUOTE_NONNUMERIC to the csv.writer invocation to quote all lines to impove security if the csv is imported into some versions of Excel.
Here is a patch that enables exporting csv with actual names of linked items instead of their ids. It adds a new action, "export_csv_names" to the "extensions" directory in your tracker.
The action works like export_csv except on columns with the Link type. The action tries to find a column called name in the linked class, or username if the class is user. If it is found, it prints this column instead of the id. Simply change the lines in the desired html pages from export_csv to export_csv_names, copy this file to the extensions directory, and that's it.
This action has been evaluated on Roundup 0.8.2 only, and was updated from the original version that ran under 0.7.
[BEWARE: get the patch from the wiki page source, not from the html display, since the wiki software removes quotes. Any suggestions of a better way to put this patch online are welcome.]
Code is also posted to this pastebin URL: http://pastebin.com/f4f6ad0c0 .
ExportCSVNamesAction.py:
1 from roundup.cgi.actions import Action
2 from roundup.cgi import templating
3 from roundup import hyperdb
4
5 import csv
6
7 class ExportCSVNamesAction(Action):
8 name = 'export'
9 permissionType = 'View'
10
11 def handle(self):
12 ''' Export the specified search query as CSV. '''
13 # figure the request
14 request = templating.HTMLRequest(self.client)
15 filterspec = request.filterspec
16 sort = request.sort
17 group = request.group
18 columns = request.columns
19 klass = self.db.getclass(request.classname)
20
21 # full-text search
22 if request.search_text:
23 matches = self.db.indexer.search(
24 re.findall(r'\b\w{2,25}\b', request.search_text), klass)
25 else:
26 matches = None
27
28 h = self.client.additional_headers
29 h['Content-Type'] = 'text/csv; charset=%s' % self.client.charset
30 # some browsers will honor the filename here...
31 h['Content-Disposition'] = 'inline; filename=query.csv'
32
33 self.client.header()
34
35 if self.client.env['REQUEST_METHOD'] == 'HEAD':
36 # all done, return a dummy string
37 return 'dummy'
38
39 wfile = self.client.request.wfile
40 if self.client.charset != self.client.STORAGE_CHARSET:
41 wfile = codecs.EncodedFile(wfile,
42 self.client.STORAGE_CHARSET, self.client.charset, 'replace')
43
44 writer = csv.writer(wfile, quoting=csv.QUOTE_NONNUMERIC)
45 self.client._socket_op(writer.writerow, columns)
46
47 # Figure out Link columns
48 represent = {}
49
50 def repr_link(cls,col):
51 def f(x):
52 if x==None:
53 return ""
54 else:
55 return str(cls.get(x,col))
56 return f
57
58 props = klass.getprops()
59
60 for col in columns:
61 represent[col] = str
62 if isinstance(props[col], hyperdb.Link):
63 cn = props[col].classname
64 cl = self.db.getclass(cn)
65 if cl.getprops().has_key('name'):
66 represent[col] = repr_link(cl, 'name')
67 elif cn == 'user':
68 represent[col] = repr_link(cl, 'username')
69
70 # and search
71 for itemid in klass.filter(matches, filterspec, sort, group):
72 self.client._socket_op(writer.writerow, [represent[col](klass.get(itemid, col)) for col in columns])
73
74 return '\n'
75
76 def init(instance):
77 instance.registerAction('export_csv_names', ExportCSVNamesAction)
78
79
80 # vim: set filetype=python sts=4 sw=4 et si