summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2011-02-01 14:44:38 +0100
committerÉtienne Loks <etienne.loks@peacefrogs.net>2011-02-01 14:44:38 +0100
commit6e76724c700da8a77cc64c96262c6a685ad5382b (patch)
tree2f72b6a7238cb9ca83fa7675b3ee27f747a05628
parent989c625b2b4f580822c0e59146d36e66342accea (diff)
downloadIshtar-6e76724c700da8a77cc64c96262c6a685ad5382b.tar.bz2
Ishtar-6e76724c700da8a77cc64c96262c6a685ad5382b.zip
Better management of CSV files (refs #159) and grids
-rw-r--r--ishtar/furnitures/forms.py10
-rw-r--r--ishtar/furnitures/models.py9
-rw-r--r--ishtar/furnitures/views.py199
-rw-r--r--ishtar/furnitures/widgets.py37
4 files changed, 111 insertions, 144 deletions
diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py
index e436d0664..d73f3e849 100644
--- a/ishtar/furnitures/forms.py
+++ b/ishtar/furnitures/forms.py
@@ -668,12 +668,14 @@ class FileWizard(Wizard):
return res
class FileSelect(forms.Form):
- town = forms.IntegerField(label=_(u"Town"),
+ towns = forms.IntegerField(label=_(u"Town"),
widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \
'autocomplete-town', associated_model=models.Town),
validators=[models.valid_id(models.Town)])
file_type = forms.ChoiceField(label=_("File type"),
choices=models.FileType.get_types())
+ saisine_type = forms.ChoiceField(label=_("Saisine type"),
+ choices=models.SaisineType.get_types())
year = forms.IntegerField(label=_("Year"))
class FileFormSelection(forms.Form):
@@ -682,7 +684,7 @@ class FileFormSelection(forms.Form):
currents = {'pk':models.File}
pk = forms.IntegerField(label="", required=False,
widget=widgets.JQueryJqGrid(reverse_lazy('get-file'),
- FileSelect(), ['file_type', 'year']),
+ FileSelect(), models.File),
validators=[models.valid_id(models.File)])
def clean(self):
@@ -1161,6 +1163,8 @@ class OperationSelect(forms.Form):
validators=[models.valid_id(models.Town)])
operation_type = forms.ChoiceField(label=_("Operation type"),
choices=models.OperationType.get_types())
+ remains = forms.ChoiceField(label=_("Remains"),
+ choices=models.RemainType.get_types())
year = forms.IntegerField(label=_("Year"))
class OperationFormSelection(forms.Form):
@@ -1169,7 +1173,7 @@ class OperationFormSelection(forms.Form):
currents = {'pk':models.Operation}
pk = forms.IntegerField(label="", required=False,
widget=widgets.JQueryJqGrid(reverse_lazy('get-operation'),
- OperationSelect(), ['operation_type', 'year']),
+ OperationSelect(), models.Operation),
validators=[models.valid_id(models.Operation)])
def clean(self):
diff --git a/ishtar/furnitures/models.py b/ishtar/furnitures/models.py
index 2b82fe6b4..c45f18c08 100644
--- a/ishtar/furnitures/models.py
+++ b/ishtar/furnitures/models.py
@@ -271,6 +271,8 @@ if settings.COUNTRY == 'fr':
verbose_name_plural = u"Types Saisine"
class File(BaseHistorizedItem, OwnPerms):
+ TABLE_COLS = ['numeric_reference', 'year', 'internal_reference',
+ 'file_type', 'saisine_type', 'towns', ]
year = models.IntegerField(_(u"Year"),
default=lambda:datetime.datetime.now().year)
numeric_reference = models.IntegerField(_(u"Numeric reference"))
@@ -288,7 +290,7 @@ class File(BaseHistorizedItem, OwnPerms):
permit_reference = models.CharField(_(u"Permit reference"),
max_length=60, blank=True, null=True)
is_active = models.BooleanField(_(u"Is active?"), default=True)
- towns = models.ManyToManyField("Town")
+ towns = models.ManyToManyField("Town", verbose_name=_(u"Towns"))
creation_date = models.DateField(_(u"Creation date"),
default=datetime.datetime.now)
reception_date = models.DateField(_(u'Reception date'), blank=True,
@@ -347,6 +349,8 @@ class RemainType(GeneralType):
verbose_name_plural = _(u"Remain types")
class Operation(BaseHistorizedItem, OwnPerms):
+ TABLE_COLS = ['operation_code', 'year', 'operation_type',
+ 'remains', 'towns', 'associated_file']
start_date = models.DateField(_(u"Start date"), null=True, blank=True)
end_date = models.DateField(_(u"Closing date"), null=True, blank=True)
in_charge = models.ForeignKey('Person', related_name='+', null=True,
@@ -364,6 +368,7 @@ class Operation(BaseHistorizedItem, OwnPerms):
blank=True)
code_dracar = models.CharField(u"Code DRACAR", max_length=10, null=True,
blank=True)
+ TABLE_COLS += ["code_patriarche", "code_dracar"]
comment = models.TextField(_(u"Comment"), null=True, blank=True)
history = HistoricalRecords()
@@ -694,7 +699,7 @@ class Town(models.Model):
def __unicode__(self):
if settings.COUNTRY == "fr":
- return " - ".join((self.name, self.numero_insee))
+ return u"%s (%s)" % (self.name, self.numero_insee)
return self.name
class TreatmentType(GeneralType):
diff --git a/ishtar/furnitures/views.py b/ishtar/furnitures/views.py
index 3b6263517..ec61ad339 100644
--- a/ishtar/furnitures/views.py
+++ b/ishtar/furnitures/views.py
@@ -25,6 +25,8 @@ import csv
import json
import datetime
+CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL}
+
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
@@ -123,65 +125,86 @@ def autocomplete_file(request):
for file in files])
return HttpResponse(data, mimetype='text/plain')
-def get_file(request, type='json'):
- if not type:
- type = 'json'
- request_keys = {'town':'towns__pk',
- 'file_type':'file_type__pk',
- 'year':'year',
- 'value':'name',
- }
- dct = {}
- for k in request_keys:
- q = request.GET.get(k)
- if not q:
- continue
- dct[request_keys[k]] = q
- if not dct:
- if 'get_file' in request.session:
- dct = request.session['get_file']
- elif 'file' in request.session:
- dct = {"pk":request.session['file']}
+def get_item(model, func_name, default_name):
+ """
+ Generic treatment of tables
+ """
+ def func(request, type='json', **dct):
+ if not type:
+ type = 'json'
+ request_keys = dict([(field.name,
+ field.name + (hasattr(field, 'rel') and '__pk' or ''))
+ for field in model._meta.fields])
+ dct = {}
+ for k in request_keys:
+ q = request.GET.get(k)
+ if not q:
+ continue
+ dct[request_keys[k]] = q
if not dct:
- return HttpResponse(mimetype='text/plain')
- else:
- request.session['get_file'] = dct
- query = Q(**dct)
- files = models.File.objects.filter(query)
- q = request.GET.get('sidx')
- if q and q in request_keys:
- k = request_keys[q]
- if k.endswith("__pk"):
- k = k[:-len("__pk")] + "__label"
- q = request.GET.get('sord')
- sign = q and q == u'desc' and "-" or ''
- if k == "name":
- files = files.order_by(sign + 'year').order_by(
- sign + 'numeric_reference')
+ if func_name in request.session:
+ dct = request.session[func_name]
+ elif default_name in request.session:
+ dct = {"pk":request.session[default_name]}
+ if not dct:
+ return HttpResponse(mimetype='text/plain')
else:
- files = files.order_by(sign + k)
- data = None
- if type == "json":
- data = json.dumps({
- "records":len(files),
- "rows":[{"id":unicode(fle.pk),
- "cell":(unicode(fle.pk), unicode(fle),
- unicode(fle.file_type), unicode(fle.year))}
- for fle in files]
- })
- return HttpResponse(data, mimetype='text/plain')
- elif type == "csv":
- response = HttpResponse(mimetype='text/csv')
- n = datetime.datetime.now()
- filename = u'files_%s.csv' % n.strftime('%Y%m%d-%H%M%S')
- response['Content-Disposition'] = 'attachment; filename=%s' % filename
- writer = csv.writer(response)
- for fle in files:
- writer.writerow([unicode(fle).encode('utf-8'),
- unicode(fle.file_type).encode('utf-8'),
- unicode(fle.year).encode('utf-8')])
- return response
- return HttpResponse(data, mimetype='text/plain')
+ request.session[func_name] = dct
+ query = Q(**dct)
+ items = model.objects.filter(query)
+ q = request.GET.get('sidx')
+ if q and q in request_keys:
+ k = request_keys[q]
+ if k.endswith("__pk"):
+ k = k[:-len("__pk")] + "__label"
+ q = request.GET.get('sord')
+ sign = q and q == u'desc' and "-" or ''
+ items = items.order_by(sign + k)
+ datas = []
+ f = items[0]
+ for item in items:
+ data = [item.pk]
+ for k in model.TABLE_COLS:
+ val = getattr(item, k)
+ if hasattr(val, 'all'): # manage related objects
+ data.append(", ".join([v and unicode(v) or u""
+ for v in getattr(val, 'all')()]))
+ else:
+ data.append(val and unicode(val) or u"")
+ datas.append(data)
+ if type == "json":
+ rows = []
+ for data in datas:
+ rows.append({"id":unicode(data[0]),
+ "cell":data})
+ data = json.dumps({
+ "records":len(items),
+ "rows":rows
+ })
+ return HttpResponse(data, mimetype='text/plain')
+ elif type == "csv":
+ response = HttpResponse(mimetype='text/csv')
+ n = datetime.datetime.now()
+ filename = u'%s_%s.csv' % (default_name, n.strftime('%Y%m%d-%H%M%S'))
+ response['Content-Disposition'] = 'attachment; filename=%s' % filename
+ writer = csv.writer(response, **CSV_OPTIONS)
+ col_names = []
+ for field_name in model.TABLE_COLS:
+ try:
+ field = model._meta.get_field(field_name)
+ except:
+ col_names.append(u"".encode('utf-8'))
+ continue
+ col_names.append(unicode(field.verbose_name).encode('utf-8'))
+ writer.writerow(col_names)
+ for data in datas:
+ writer.writerow([val.encode('utf-8') for val in data[1:]])
+ return response
+ return HttpResponse(None, mimetype='text/plain')
+
+ return func
+
+get_file = get_item(models.File, 'get_file', 'file')
def autocomplete_operation(request, non_closed=True):
if not request.GET.get('term'):
@@ -204,67 +227,7 @@ def autocomplete_operation(request, non_closed=True):
for operation in operations])
return HttpResponse(data, mimetype='text/plain')
-def get_operation(request, type='json', non_closed=True):
- if not type:
- type = 'json'
- request_keys = {'town':'towns__pk',
- 'operation_type':'operation_type__pk',
- 'operation_code':'operation_code',
- 'year':'year',
- 'value':'name',
- }
- dct = {}
- for k in request_keys:
- q = request.GET.get(k)
- if not q:
- continue
- dct[request_keys[k]] = q
- if not dct:
- if 'get_operation' in request.session:
- dct = request.session['get_operation']
- elif 'operation' in request.session:
- dct = {"pk":request.session['operation']}
- if not dct:
- return HttpResponse(mimetype='text/plain')
- else:
- request.session['get_operation'] = dct
- query = Q(**dct)
- operations = models.Operation.objects.filter(query)
- q = request.GET.get('sidx')
- if q and q in request_keys:
- k = request_keys[q]
- if k.endswith("__pk"):
- k = k[:-len("__pk")] + "__label"
- q = request.GET.get('sord')
- sign = q and q == u'desc' and "-" or ''
- if k == "name":
- k = "operation_code"
- operations = operations.order_by(sign + 'year').order_by(
- sign + 'operation_code')
- else:
- operations = operations.order_by(sign + k)
- data = None
- if type == 'json':
- data = json.dumps({
- "records":len(operations),
- "rows":[{"id":unicode(operation.pk),
- "cell":(unicode(operation.pk), unicode(operation),
- unicode(operation.operation_type), unicode(operation.year))}
- for operation in operations]
- })
- return HttpResponse(data, mimetype='text/plain')
- elif type == "csv":
- response = HttpResponse(mimetype='text/csv')
- n = datetime.datetime.now()
- filename = 'operations_%s.csv' % n.strftime('%Y%m%d-%H%M%S')
- response['Content-Disposition'] = 'attachment; filename=%s' % filename
- writer = csv.writer(response)
- for ope in operations:
- writer.writerow([unicode(ope).encode('utf-8'),
- unicode(ope.operation_type).encode('utf-8'),
- unicode(ope.year).encode('utf-8')])
- return response
- return HttpResponse(data, mimetype='text/plain')
+get_operation = get_item(models.Operation, 'get_operation', 'operation')
def autocomplete_organization(request, orga_type=None):
if not request.GET.get('term'):
diff --git a/ishtar/furnitures/widgets.py b/ishtar/furnitures/widgets.py
index 932770f29..439eb81fa 100644
--- a/ishtar/furnitures/widgets.py
+++ b/ishtar/furnitures/widgets.py
@@ -129,22 +129,14 @@ class JQueryJqGrid(forms.RadioSelect):
]
css = {'all':['%s/media/ui.jqgrid.css' % settings.MEDIA_URL]}
- def __init__(self, source, form, cols, attrs={}):
+ def __init__(self, source, form, associated_model, attrs={}):
self.source = source
self.form = form
self.attrs = attrs
- self.cols = cols
+ self.associated_model = associated_model
def render(self, name, value=None, attrs=None):
rendered = unicode(self.form)
- """
- for k in self.form.fields:
- field = self.form.fields[k]
- print unicode(field)
- print field.label_tag
- rendered += u"<tr><td>%s</td><td>%s</td></tr>" % (field.label_tag,
- unicode(field))
- """
rendered += """
</table>
<button id='search_%s' class='submit'>%s</button>
@@ -155,12 +147,16 @@ class JQueryJqGrid(forms.RadioSelect):
for k in self.form.fields:
field = self.form.fields[k]
col_idx.append(u'"%s"' % k)
- if k in self.cols:
- col_names.append(u'"%s"' % field.label)
- extra_cols.append(self.COL_TPL % {'idx':k})
- col_names = col_names and ",".join([""]+col_names) or ""
- col_idx = col_idx and ",".join(col_idx) or ""
- extra_cols = extra_cols and ",".join([""]+extra_cols) or ""
+ for field_name in self.associated_model.TABLE_COLS:
+ try:
+ field = self.associated_model._meta.get_field(field_name)
+ except:
+ continue
+ col_names.append(u'"%s"' % field.verbose_name)
+ extra_cols.append(self.COL_TPL % {'idx':field.name})
+ col_names = col_names and ",\n".join(col_names) or ""
+ col_idx = col_idx and ",\n".join(col_idx) or ""
+ extra_cols = extra_cols and ",\n".join(extra_cols) or ""
rendered += """<table id="grid_%s" class='jqgrid'></table>
<div id="pager_%s"></div>
""" % (name, name)
@@ -199,10 +195,10 @@ jQuery("#grid_%(name)s").jqGrid({
url:'%(source)s',
datatype: "json",
mtype: 'GET',
- colNames:['id', '%(name_label)s'%(col_names)s],
+ colNames:['id', %(col_names)s],
colModel:[
{name:'id', index:'id', hidden:true},
-{name:'value', index:'value'}%(extra_cols)s
+%(extra_cols)s
],
sortname: 'value',
viewrecords: true,
@@ -217,8 +213,7 @@ jQuery("#grid_%(name)s").jqGrid({
});
</script>
""" % {'name':name, 'col_names':col_names, 'extra_cols':extra_cols,
- 'name_label':unicode(_("Name")), 'source':unicode(self.source),
- 'col_idx':col_idx, 'no_result':unicode(_("No results")),
- 'loading':unicode(_("Loading..."))}
+ 'source':unicode(self.source), 'col_idx':col_idx,
+ 'no_result':unicode(_("No results")), 'loading':unicode(_("Loading..."))}
return rendered