diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-09-18 01:21:02 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2012-09-18 01:21:02 +0200 |
commit | 919f1da7d1afac6c39bc12f86b979272b0dd5483 (patch) | |
tree | 9239f3ee7af9289fa3b417d6494948c7bd210c3b /chimere/utils.py | |
parent | 432e3ee5db3745502e47091199d9677f00d69339 (diff) | |
download | Chimère-919f1da7d1afac6c39bc12f86b979272b0dd5483.tar.bz2 Chimère-919f1da7d1afac6c39bc12f86b979272b0dd5483.zip |
Work on CSV export
Diffstat (limited to 'chimere/utils.py')
-rw-r--r-- | chimere/utils.py | 156 |
1 files changed, 154 insertions, 2 deletions
diff --git a/chimere/utils.py b/chimere/utils.py index 60b2dac..a24e22f 100644 --- a/chimere/utils.py +++ b/chimere/utils.py @@ -21,6 +21,7 @@ Utilitaries """ +import csv import datetime import os import re @@ -429,10 +430,161 @@ class ShapefileManager(ImportManager): buff.close() return filename, zip_stream -RE_HOOK = re.compile('\[([^\]]*)\]') +class ImportManager: + u""" + Generic class for specific importers + """ + default_source = None + def __init__(self, importer_instance): + self.importer_instance = importer_instance + self.default_name = " - ".join([cat.name + for cat in self.importer_instance.categories.order_by('name').all()]) + + def get(self): + pass + + def put(self): + pass + + def create_or_update_item(self, cls, values, import_key, version=None): + updated, created, item = False, False, None + if import_key: + dct_import = { + 'import_key__icontains':'%s:%s;' % ( + self.importer_instance.importer_type, + import_key), + 'import_source':self.importer_instance.source} + try: + item = cls.objects.get(**dct_import) + if version and item.import_version == int(version): + # no update since the last import + return item, None, None + for k in values: + setattr(item, k, values[k]) + try: + item.save() + except TypeError: + # error on data source + return None, False, False + updated = True + except ObjectDoesNotExist: + pass + if not item: + values.update({ + 'import_source':self.importer_instance.source}) + values['status'] = 'I' + try: + item = cls.objects.create(**values) + except TypeError: + # error on data source + return None, False, False + created = True + if import_key: + item.set_key(self.importer_instance.importer_type, + import_key) + item.categories.clear() + for cat in self.importer_instance.categories.all(): + item.categories.add(cat) + return item, updated, created + @classmethod + def get_files_inside_zip(cls, zippedfile, suffixes, dest_dir=None): + try: + flz = zipfile.ZipFile(zippedfile) + except zipfile.BadZipfile: + return [], _(u"Bad zip file") + namelist = flz.namelist() + filenames = [] + for suffix in suffixes: + current_file_name = None + for name in namelist: + if name.endswith(suffix) \ + or name.endswith(suffix.lower()) \ + or name.endswith(suffix.upper()): + current_file_name = name + filenames.append(current_file_name) + files = [] + for filename in filenames: + if filename: + if dest_dir: + files.append(filename) + flz.extract(filename, dest_dir) + else: + files.append(flz.open(filename)) + else: + files.append(None) + return files + + def get_source_file(self, source, suffixes, dest_dir=None, + extra_url=None): + if not hasattr(source, 'read'): + if not source: + source = self.importer_instance.source \ + if self.importer_instance.source else self.default_source + try: + url = source + if extra_url: + url += extra_url + remotehandle = urllib2.urlopen(url) + source = StringIO.StringIO(remotehandle.read()) + remotehandle.close() + except ValueError: + # assume it is a local file + try: + source = open(source) + except IOError, msg: + return (None, msg) + except urllib2.URLError as error: + return (None, error.message) + if self.importer_instance.zipped: + try: + files = self.get_files_inside_zip(source, suffixes, dest_dir) + except zipfile.BadZipfile: + return (None, _(u"Bad zip file")) + if not files or None in files: + return (None, + _(u"Missing file(s) inside the zip file")) + source = files[0] if len(suffixes) == 1 else files + return (source, None) + +class CSVManager(ImportManager): + u""" + CSV importer + """ + _COLS = [("Id", 'pk'), (_(u"Name"), 'name'), + (_(u"Categories"), lambda obj:", ".join( + [c.name for c in obj.categories.all()])), + (_(u"State"), 'status')] + COLS = {'marker':_COLS+[(_(u"Description"), 'description'), + (_(u"Localisation"), lambda obj: obj.point.wkt)], + 'route':_COLS+[(_(u"Localisation"), lambda obj: obj.route.wkt)]} + + @classmethod + def export(cls, queryset): + dct = {'description':unicode(datetime.date.today()), 'data':[]} + cls_name = queryset.model.__name__.lower() + cols = cls.COLS[cls_name][:] + for pm in queryset.model.properties(): + cols.append((pm.name, pm.getAttrName())) + header = [lbl for lbl, attr in cols] + dct['data'].append(header) + for item in queryset.all(): + data = [] + for lbl, attr in cols: + if callable(attr): + data.append(attr(item)) + print lbl, attr(item) + else: + data.append(getattr(item, attr)) + dct['data'].append(data) + filename = unicode_normalize(settings.PROJECT_NAME + dct['description']\ + + '.csv') + result = render_to_response('chimere/export_%s.csv' % cls_name, dct) + return filename, result + +RE_HOOK = re.compile('\[([^\]]*)\]') -# manage deleted item from OSM +# TODO: manage deleted item from OSM class OSMManager(ImportManager): u""" |