f3750dcd539f5dbd1670545da9254f6b7964aaf0
1 # -*- encoding: utf-8 -*-
4 from StringIO
import StringIO
6 from odf
.opendocument
import OpenDocumentSpreadsheet
7 from odf
.style
import Style
, TextProperties
, TableColumnProperties
9 from odf
.table
import Table
, TableRow
, TableCell
11 from django
.core
.urlresolvers
import reverse
12 from django
.contrib
import admin
13 from django
.utils
.functional
import update_wrapper
14 from django
.http
import HttpResponse
16 # Create a notation similar to queryset filter
19 # String return if lookup property failed
25 if not isinstance(msg
, unicode):
27 text
= unicode (msg
, "utf-8")
33 class ExportAdmin(admin
.ModelAdmin
):
34 change_list_template
= 'admin/export/change_list.html'
36 def changelist_view(self
, request
, extra_context
=None):
38 Add export URL for the template
40 if extra_context
is None:
42 extra_context
.update({
43 'export_csv_url' : reverse("admin:%s_%s_export_csv" % (self
.model
._meta
.app_label
, self
.model
._meta
.module_name
)),
44 'export_ods_url' : reverse("admin:%s_%s_export_ods" % (self
.model
._meta
.app_label
, self
.model
._meta
.module_name
)),
46 return super(ExportAdmin
, self
).changelist_view(request
, extra_context
)
50 from django
.conf
.urls
.defaults
import patterns
, url
52 urls
= super(ExportAdmin
, self
).get_urls()
53 info
= self
.model
._meta
.app_label
, self
.model
._meta
.module_name
55 urlpatterns
= patterns('',
57 self
.admin_site
.admin_view(self
.export_csv
),
58 name
='%s_%s_export_csv' % info
),
60 self
.admin_site
.admin_view(self
.export_ods
),
61 name
='%s_%s_export_ods' % info
),
63 return urlpatterns
+ urls
65 def get_object_value(self
, obj
, header
):
67 Function which work as a queryset filter access :
68 Father -- Kid (One2One father related_name = 'child')
71 It tries to resolve the property from header string, through
72 linked object if needed. If it can't load any value, empty
75 segments
= header
.split(SEPARATOR
)
78 if len(segments
) == 0:
79 return getattr(obj
, prop
, EMPTY
)
82 child
= getattr(obj
, prop
, None)
83 return self
.get_object_value(child
, ".".join(segments
))
87 def get_default_export_fields(self
):
88 fields_name
= [f
.name
for f
in self
.model
._meta
.fields
]
89 for fk
in self
.model
._meta
._related_objects_cache
.keys():
90 fields_name
= fields_name
+ [u
"%s%s%s" % (fk
.var_name
, SEPARATOR
, f
.name
) for f
in fk
.model
._meta
.fields
]
94 def get_export_fields(self
):
96 This property is a list of string, which should have queryset filter notation style (with X2 underscore).
97 If there is no fields, the models is full introspected, stop at 1 depth level.
100 export_fields
= getattr(self
, 'export_fields', None)
102 if export_fields
is None:
103 export_fields
= getattr(self
, 'csv_fields', None)
105 if export_fields
is None:
106 export_fields
= self
.get_default_export_fields()
110 def export_ods(self
, request
):
112 Generate HTTP response as ODS file from export_fields property.
114 export_fields
= self
.get_export_fields()
116 qs
= self
.queryset(request
)
118 response
= HttpResponse(mimetype
='application/vnd.oasis.opendocument.spreadsheet')
119 response
['Content-Disposition'] = 'attachment; filename=%s.ods' % unicode(self
.model
._meta
.verbose_name_plural
)
121 doc
= OpenDocumentSpreadsheet()
122 style
= Style(name
="Large number", family
="table-cell")
123 style
.addElement(TextProperties(fontfamily
="Arial", fontsize
="15pt"))
124 doc
.styles
.addElement(style
)
125 widewidth
= Style(name
="co1", family
="table-column")
126 widewidth
.addElement(TableColumnProperties(columnwidth
="2.8cm", breakbefore
="auto"))
127 doc
.automaticstyles
.addElement(widewidth
)
130 if len (export_fields
) > 0:
132 table
.addElement (tr
)
133 for item
in export_fields
:
136 p
= P(stylename
= style
, text
= txt(item
))
141 table
.addElement (tr
)
143 for attr
in export_fields
:
144 value
= self
.get_object_value(o
, attr
)
147 p
= P (stylename
= style
, text
= txt(value
))
150 doc
.spreadsheet
.addElement(table
)
154 response
.write(buffer.getvalue())
157 def export_csv(self
, request
):
159 Generate HTTP response as CSV file from export_fields property.
161 csv_fields
= self
.get_export_fields()
163 qs
= self
.queryset(request
)
165 response
= HttpResponse(mimetype
='text/csv')
166 response
['Content-Disposition'] = 'attachment; filename=%s.csv' % unicode(self
.model
._meta
.verbose_name_plural
)
168 writer
= csv
.writer(response
)
171 for attr
in csv_fields
:
172 headers
.append(attr
.encode('utf-8') if isinstance(attr
, unicode) else attr
)
173 writer
.writerow(headers
)
177 for attr
in csv_fields
:
178 value
= self
.get_object_value(o
, attr
)
179 row
.append(value
.encode('utf-8') if isinstance(value
, unicode) else value
)