[IMP]Implement Import data Functionality.
bzr revid: kch@tinyerp.com-20110727064325-zh8j9w7bvcdckv7v
This commit is contained in:
parent
d0234fa5dd
commit
d196118cde
|
@ -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",
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue