[IMP]Implement Import data Functionality.

bzr revid: kch@tinyerp.com-20110727064325-zh8j9w7bvcdckv7v
This commit is contained in:
Kunal Chavda (OpenERP) 2011-07-27 12:13:25 +05:30
parent d0234fa5dd
commit d196118cde
6 changed files with 214 additions and 19 deletions

View File

@ -28,6 +28,7 @@
"static/src/js/list-editable.js",
"static/src/js/search.js",
"static/src/js/view_tree.js",
"static/src/js/import.js",
],
'css' : [
"static/lib/jquery.superfish/css/superfish.css",

View File

@ -10,7 +10,7 @@ import openerpweb.ast
import openerpweb.nonliterals
import cherrypy
import csv
# Should move to openerpweb.Xml2Json
class Xml2Json:
# xml2json-direct
@ -119,8 +119,8 @@ class WebClient(openerpweb.Controller):
%s
<script type="text/javascript">
$(function() {
QWeb = new QWeb2.Engine();
openerp.init().base.webclient("oe");
QWeb = new QWeb2.Engine();
openerp.init().base.webclient("oe");
});
</script>
<link rel="shortcut icon" href="/base/static/src/img/favicon.ico" type="image/x-icon"/>
@ -222,7 +222,7 @@ class Session(openerpweb.Controller):
context, domain = eval_context_and_domain(req.session,
openerpweb.nonliterals.CompoundContext(*(contexts or [])),
openerpweb.nonliterals.CompoundDomain(*(domains or [])))
group_by_sequence = []
for candidate in (group_by_seq or []):
ctx = req.session.eval_context(candidate, context)
@ -233,7 +233,7 @@ class Session(openerpweb.Controller):
group_by_sequence.append(group_by)
else:
group_by_sequence.extend(group_by)
return {
'context': context,
'domain': domain,
@ -246,7 +246,7 @@ class Session(openerpweb.Controller):
This method store an action object in the session object and returns an integer
identifying that action. The method get_session_action() can be used to get
back the action.
:param the_action: The action to save in the session.
:type the_action: anything
:return: A key identifying the saved action.
@ -269,7 +269,7 @@ class Session(openerpweb.Controller):
"""
Gets back a previously saved action. This method can return None if the action
was saved since too much time (this case should be handled in a smart way).
:param key: The key given by save_session_action()
:type key: integer
:return: The saved action or None.
@ -404,7 +404,7 @@ class Menu(openerpweb.Controller):
menu_items = Menus.read(menu_ids, ['name', 'sequence', 'parent_id'], context)
menu_root = {'id': False, 'name': 'root', 'parent_id': [-1, '']}
menu_items.append(menu_root)
# make a tree using parent_id
menu_items_map = dict((menu_item["id"], menu_item) for menu_item in menu_items)
for menu_item in menu_items:
@ -511,7 +511,7 @@ class DataSet(openerpweb.Controller):
record_map = dict((record['id'], record) for record in records)
return [record_map[id] for id in ids if record_map.get(id)]
@openerpweb.jsonrequest
def load(self, req, model, id, fields):
m = req.session.model(model)
@ -674,7 +674,7 @@ class View(openerpweb.Controller):
except ValueError:
# not a literal
return openerpweb.nonliterals.Domain(session, domain)
def parse_context(self, context, session):
""" Parses an arbitrary string containing a context, transforms it
to either a literal context or a :class:`openerpweb.nonliterals.Context`
@ -764,7 +764,7 @@ class SearchView(View):
if field.get('context'):
field["context"] = self.parse_domain(field["context"], req.session)
return {'fields': fields}
@openerpweb.jsonrequest
def get_filters(self, req, model):
Model = req.session.model("ir.filters")
@ -773,7 +773,7 @@ class SearchView(View):
filter["context"] = req.session.eval_context(self.parse_context(filter["context"], req.session))
filter["domain"] = req.session.eval_domain(self.parse_domain(filter["domain"], req.session))
return filters
@openerpweb.jsonrequest
def save_filter(self, req, model, name, context_to_save, domain):
Model = req.session.model("ir.filters")
@ -903,4 +903,64 @@ class Action(openerpweb.Controller):
return clean_action(req.session.model('ir.actions.server').run(
[action_id], req.session.eval_context(req.context)), req.session)
#
class Import(View):
_cp_path = "/base/import"
@openerpweb.httprequest
def import_data(self, req, session_id, callback, model, id, csvfile, csvsep, csvdel, csvcode, csvskip, fields=[]):
import StringIO
context = req.session.eval_context(req.context)
modle_obj = req.session.model(model)
res = None
content = csvfile.file.read()
print "\n content++++++++++++++++++++++++++++",content
input=StringIO.StringIO(content)
limit = 0
data = []
if not (csvdel and len(csvdel) == 1):
return "The CSV delimiter must be a single character"
try:
for j, line in enumerate(csv.reader(input, quotechar=str(csvdel), delimiter=str(csvsep))):
# If the line contains no data, we should skip it.
if not line:
continue
if j == limit:
fields = line
else:
data.append(line)
except:
return "CSV Error"
datas = []
ctx = context
if not isinstance(fields, list):
fields = [fields]
for line in data:
try:
datas.append(map(lambda x:x.decode(csvcode).encode('utf-8'), line))
except:
datas.append(map(lambda x:x.decode('latin').encode('utf-8'), line))
# If the file contains nothing,
if not datas:
return "The file is empty."
#Inverting the header into column names
try:
res = modle_obj.import_data(fields, datas, 'init', '', False, ctx)
except:
return "Error in Importing Data."
if res[0]>=0:
return "Successfully Imported %d objects." % (res[0],)
d = ''
for key,val in res[1].items():
d+= ('%s: %s' % (key,val))
return "Error trying to import this record :%s. ErrorMessage:%s %s" % (d,res[2],res[3])

View File

@ -87,6 +87,9 @@ openerp.base = function(instance) {
if (openerp.base.view_tree) {
openerp.base.view_tree(instance);
}
if (openerp.base.import){
openerp.base.import(instance);
}
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:

View File

@ -0,0 +1,35 @@
openerp.base.import = function(openerp) {
openerp.base.Import = openerp.base.Dialog.extend({
init: function(parent, dataset, views){
this._super(parent);
this.dataset = dataset;
this.views = views;
this.views_id = {};
for (var key in this.views) {
this.views_id[key] = this.views[key].view_id
}
},
start: function() {
var self = this
self._super(false);
self.template = 'ImportDataView';
self.dialog_title = "Import Data"
self.open({
modal: true,
width: '70%',
height: 'auto',
position: 'top',
buttons : {
"Close" : function() {
self.stop();
},
"Import File" : function() {
$("#import_data").submit();
//self.do_import();
}
},
close: function(event, ui){ self.close();}
});
},
});
}

View File

@ -212,11 +212,24 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
}
}
}
if(this.flags && this.flags.sidebar) {
if(this.$element.find('#importview')){
this.$element.find('#importview').remove()
}
if(this.active_view == 'list' || this.active_view == 'form') {
this.views[this.active_view].controller.$element.after(QWeb.render('ImportView'))
this.$element.find('#importview').click(function(ev) {
var import_view = new openerp.base.Import(self, self.dataset, self.views);
import_view.start(false);
ev.preventDefault();
});
}
}
return view_promise;
},
/**
* Event launched when a controller has been inited.
*
*
* @param {String} view_type type of view
* @param {String} view the inited controller
*/
@ -522,7 +535,7 @@ openerp.base.View = openerp.base.Controller.extend({
* Directly set a view to use instead of calling fields_view_get. This method must
* be called before start(). When an embedded view is set, underlying implementations
* of openerp.base.View must use the provided view instead of any other one.
*
*
* @param embedded_view A view.
*/
set_embedded_view: function(embedded_view) {

View File

@ -103,7 +103,7 @@
<div class="oe_login_right_pane">
<p>We think that daily job activities can be more intuitive, efficient, automated, .. and even fun.</p>
<h3>OpenERP's vision to be:</h3>
<table cellpadding="0" cellspacing="0" width="100%" style="border:none;">
<tbody>
<tr>
@ -135,7 +135,7 @@
</tr>
</tbody>
</table>
</div>
</t>
<t t-name="Header">
@ -333,7 +333,7 @@
t-att-data-index="row_index">
<t t-foreach="columns" t-as="column">
<td t-if="column.meta">
</td>
</t>
<th t-if="options.selectable" class="oe-record-selector" width="1">
@ -821,7 +821,7 @@
<option value="all">All the following conditions must match</option>
<option value="none">None of the following conditions must match</option>
</select>
<a class="searchview_extended_delete_group"
<a class="searchview_extended_delete_group"
href="javascript:void(0)"><span></span></a>
<div class="searchview_extended_propositions_list">
</div>
@ -944,4 +944,87 @@
.unwrap();
</t>
</t>
<t t-name="ImportView">
<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">
<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%">
<tr>
<td>
<table width="100%">
<tr>
<td width="100%" valign="middle" colspan="4">
<h2>1. Import a .CSV file</h2>
</td>
</tr>
<tr>
<td>
Select a .CSV file to import. If you need a sample of file to import,
you should use the export tool with the "Import Compatible" option.
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
<table align="center">
<tr>
<td><label>CSV File:</label></td>
<td>
<input type="file" id="csvfile" size="50" name="csvfile"/>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10px">
</td>
</tr>
<tr>
<td width="100%">
<div id="record">
<table width="100%">
<tr>
<td width="100%" valign="middle">
<h2>2. Check your file format</h2>
</td>
</tr>
</table>
<table id="records_data" width="100%" style="margin: 5px 0;">
</table>
<fieldset>
<legend style="cursor:pointer;">CSV Options</legend>
<table style="display:block">
<tr>
<td class="label"><label for="csv_separator">Separator:</label></td>
<td><input type="text" name="csvsep" id="csv_separator" value=","/></td>
<td class="label"><label for="csv_delimiter">Delimiter:</label></td>
<td><input type="text" name="csvdel" id="csv_delimiter" value='"'/></td>
</tr>
<tr>
<td><label for="csv_encoding">Encoding:</label></td>
<td>
<select name="csvcode" id="csv_encoding">
<option value="utf-8">UTF-8</option>
<option value="latin1">Latin 1</option>
</select>
</td>
<td><label>Lines to skip:</label></td>
<td><input type="text" name="csvskip" id="csv_skip" value="1"/></td>
</tr>
</table>
</fieldset>
</div>
</td>
</tr>
</table>
</form>
</t>
</templates>