[IMP]Improve code for import data and preview of three records.

bzr revid: kch@tinyerp.com-20110803123242-bpyq87hw0bfm0iiv
This commit is contained in:
Kunal Chavda (OpenERP) 2011-08-03 18:02:42 +05:30
parent 933c576955
commit c82c9ce5af
6 changed files with 217 additions and 18 deletions

View File

@ -40,5 +40,6 @@
"static/lib/jquery.ui.notify/css/ui.notify.css",
"static/src/css/base.css",
"static/src/css/data_export.css",
"static/src/css/data_import.css",
],
}

View File

@ -1204,8 +1204,86 @@ class Export(View):
class Import(View):
_cp_path = "/base/import"
def fields_get(self, req, model):
Model = req.session.model(model)
fields = Model.fields_get(False, req.session.eval_context(req.context))
return fields
@openerpweb.httprequest
def import_data(self, req, session_id, callback, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]):
def detect_data(self, req, session_id, model, id, csvfile, csvsep, csvdel, csvcode, csvskip):
import StringIO
_fields = {}
_fields_invert = {}
error = None
fields = dict(req.session.model(model).fields_get(False, req.session.eval_context(req.context)))
fields.update({'id': {'string': 'ID'}, '.id': {'string': 'Database ID'}})
def model_populate(fields, prefix_node='', prefix=None, prefix_value='', level=2):
def str_comp(x,y):
if x<y: return 1
elif x>y: return -1
else: return 0
fields_order = fields.keys()
fields_order.sort(lambda x,y: str_comp(fields[x].get('string', ''), fields[y].get('string', '')))
for field in fields_order:
if (fields[field].get('type','') not in ('reference',))\
and (not fields[field].get('readonly')\
or not dict(fields[field].get('states', {}).get(
'draft', [('readonly', True)])).get('readonly',True)):
st_name = prefix_value+fields[field]['string'] or field
_fields[prefix_node+field] = st_name
_fields_invert[st_name] = prefix_node+field
if fields[field].get('type','')=='one2many' and level>0:
fields2 = self.fields_get(req, fields[field]['relation'])
model_populate(fields2, prefix_node+field+'/', None, st_name+'/', level-1)
if fields[field].get('relation',False) and level>0:
model_populate({'/id': {'type': 'char', 'string': 'ID'}, '.id': {'type': 'char', 'string': 'Database ID'}},
prefix_node+field, None, st_name+'/', level-1)
fields.update({'id':{'string':'ID'},'.id':{'string':'Database ID'}})
model_populate(fields)
try:
data = csv.reader(csvfile.file, quotechar=str(csvdel), delimiter=str(csvsep))
except:
raise 'Error opening .CSV file', 'Input Error.'
records = []
fields = []
word=''
limit = 3
try:
for i, row in enumerate(data):
records.append(row)
if i == limit:
break
for line in records:
for word in line:
word = str(word.decode(csvcode))
if word in _fields:
fields.append((word, _fields[word]))
elif word in _fields_invert.keys():
fields.append((_fields_invert[word], word))
else:
error = {'message':("You cannot import the field '%s', because we cannot auto-detect it" % (word,))}
break
except:
error = {'message':('Error processing the first line of the file. Field "%s" is unknown') % (word,)}
if error:
csvfile.file.seek(0)
error=dict(error, preview=csvfile.file.read(200))
return simplejson.dumps({'error':error})
return simplejson.dumps({'records':records})
@openerpweb.httprequest
def import_data(self, req, session_id, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]):
import StringIO
context = req.session.eval_context(req.context)
@ -1217,7 +1295,8 @@ class Import(View):
data = []
if not (csvdel and len(csvdel) == 1):
return "The CSV delimiter must be a single character"
error={'message': "The CSV delimiter must be a single character"}
return simplejson.dumps({'error':error})
try:
for j, line in enumerate(csv.reader(input, quotechar=str(csvdel), delimiter=str(csvsep))):
@ -1228,8 +1307,9 @@ class Import(View):
fields = line
else:
data.append(line)
except:
return "CSV Error"
except csv.Error, e:
error={'message': str(e),'title': 'File Format Error'}
return simplejson.dumps({'error':error})
datas = []
ctx = context
@ -1245,19 +1325,24 @@ class Import(View):
# If the file contains nothing,
if not datas:
return "The file is empty."
error = {'message': 'The file is empty !', 'title': 'Importation !'}
return simplejson.dumps({'error':error})
#Inverting the header into column names
try:
res = modle_obj.import_data(fields, datas, 'init', '', False, ctx)
except:
return "Error in Importing Data."
except Exception, e:
error = {'message':str(e), 'title':'XML-RPC error'}
return simplejson.dumps({'error':error})
if res[0]>=0:
return "Successfully Imported %d objects." % (res[0],)
success={'message':'Imported %d objects' % (res[0],)}
return simplejson.dumps({'success':success})
d = ''
for key,val in res[1].items():
d+= ('%s: %s' % (key,val))
d+= ('%s: %s' % (str(key),str(val)))
msg = 'Error trying to import this record:%s. ErrorMessage:%s %s' % (d,res[2],res[3])
error = {'message':str(msg), 'title':'ImportationError'}
return "Error trying to import this record :%s. ErrorMessage:%s %s" % (d,res[2],res[3])
return simplejson.dumps({'error':error})

View File

@ -0,0 +1,23 @@
.grid {
border: none;
border-collapse: collapse;
}
.grid-header .grid-cell {
background: url(../img/gradientlinebg.gif);
border-bottom: 1px solid #E3E3E3;
font-weight: bold;
text-align: left;
}
.grid-row .grid-cell {
border-bottom: 1px solid #E3E3E3;
}
.openerp .separator.horizontal {
font-weight: bold;
border-bottom-width: 1px;
margin: 6px 4px 6px 1px;
height: 20px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

View File

@ -24,12 +24,86 @@ openerp.base.Import = openerp.base.Dialog.extend({
self.stop();
},
"Import File" : function() {
$("#import_data").submit();
//self.do_import();
//$("#import_data").submit();
self.do_import();
}
},
close: function(event, ui){ self.stop();}
});
this.$element.find('#csvfile').change(this.on_autodetect_data);
this.$element.find('fieldset legend').click(function () {
$(this).next().toggle();
});
},
do_import: function() {
var self = this;
if(!this.$element.find('#csvfile').val()) { return; }
this.$element.find('#import_data').attr({
'action': '/base/import/import_data'
}).ajaxSubmit({
success: this.import_results
});
},
on_autodetect_data: function() {
var self = this;
if(this.$element.find("#res td")){
this.$element.find("#res td").remove();
this.$element.find("#imported_success").css('display','none');
}
if(!this.$element.find('#csvfile').val()) { return; }
this.$element.find('#import_data').attr({
'action': '/base/import/detect_data'
}).ajaxSubmit({
success: this.import_results
});
},
import_results:function(res){
var self = this;
var results = $.parseJSON(res);
if (results['records']){
var result = results['records'];
if ($('#error').find('table')){
$("#error table").remove();
}
if ($('#records_data').find('tr')){
$("#records_data tr").remove();
}
for (i in result) {
if (i == 0){
$('#records_data').append('<tr class="grid-header"></tr>');
for (m in result[i]){
$('.grid-header').append('<th class="grid-cell">'+result[i][m]+'</th>');
}
}else{
$('#records_data tr:last').after('<tr id='+i+' class="grid-row"></tr>');
for (n in result[i]){
$("tr[id="+i+"]").append('<td class="grid-cell">'+result[i][n]+'</td>');
}
}
}
}else if(results['error']){
var result = results['error'];
if ($('#records_data').find('tr')){
$("#records_data tr").remove();
}
if ($('#error').find('table')){
$("#error table").remove();
}
$("#error").append('<table id="error_tbl"><tr style="white-space: pre-line;">The import failed due to:'+result['message']+'</tr></table>');
if (result['preview']){
$("#error_tbl tr:last").after('<tr>Here is a preview of the file we could not import:</tr>');
$("#error_tbl tr:last").after('<tr><pre>'+result['preview']+'</pre></tr>');
}
}else if(results['success']){
var result = results['success'];
$("#imported_success").css('display','block');
$("#res").append('<td>'+result['message']+'</td>')
}
},
stop: function() {
$(this.$dialog).remove();
this._super();
},
});
}

View File

@ -1280,9 +1280,8 @@
<a id="importview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Import</a>
</t>
<t t-name="ImportDataView">
<form name="import_data" id="import_data" action="/base/import/import_data" method="post" enctype="multipart/form-data">
<form name="import_data" id="import_data" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="session_id" t-att-value="session.session_id"/>
<input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/>
<input type="hidden" name="model" t-att-value="dataset.model"/>
<input type="hidden" name="id" t-att-value="dataset.id"/>
<table cellspacing="5" border="0" width="100%">
@ -1291,7 +1290,7 @@
<table width="100%">
<tr>
<td width="100%" valign="middle" colspan="4">
<h2>1. Import a .CSV file</h2>
<h2 class="separator horizontal">1. Import a .CSV file</h2>
</td>
</tr>
<tr>
@ -1325,15 +1324,17 @@
<table width="100%">
<tr>
<td width="100%" valign="middle">
<h2>2. Check your file format</h2>
<h2 class="separator horizontal">2. Check your file format</h2>
</td>
</tr>
</table>
<table id="records_data" width="100%" style="margin: 5px 0;">
<div id="error">
</div>
<table id="records_data" class="grid" width="100%" style="margin: 5px 0;">
</table>
<fieldset>
<legend style="cursor:pointer;">CSV Options</legend>
<table style="display:block">
<table style="display:none">
<tr>
<td class="label"><label for="csv_separator">Separator:</label></td>
<td><input type="text" name="csvsep" id="csv_separator" value=","/></td>
@ -1356,6 +1357,21 @@
</div>
</td>
</tr>
<tr>
<td width="100%">
<div id="imported_success" style="display:none;">
<table width="100%">
<tr>
<td width="100%" valign="middle" colspan="4">
<h2 class="separator horizontal">3. File imported</h2>
</td>
</tr>
<tr id="res">
</tr>
</table>
</div>
</td>
</tr>
</table>
</form>
</t>