在 Odoo 9 中一次上传多个附件

Upload multiple attachment at once in Odoo 9

我正在尝试在 Odoo 中创建一个功能,允许用户从附件表单上传多个文件,当他提交时,它会创建与所选文档一样多的附件。

我为 'binary' 字段创建了一个允许多选的小部件(在 Qweb 模板中向 'input' 标记添加 'multiple' 参数),但此时我努力创建附件并link将它们与 JS 的相关字段结合起来。

我的小部件:

odoo.define('lettermgmt', function(require)
{
    'use strict';
    var core = require('web.core');
    var FieldBinaryFile = core.form_widget_registry.get('binary');
    var FieldBinaryMultipleFiles = FieldBinaryFile.extend({
        template : 'FieldBinaryMultipleFiles',
    });
    core.form_widget_registry.add('binary_multiple_files',FieldBinaryMultipleFiles);

});

我的第一个猜测是重写 on_file_change 方法,循环“e.target.files”并对“/web/binary/upload_attachment”上的每个文件发出 POST 请求。这会创建附件,但我不知道如何将它们 link 添加到我的模型(关系字段)。

我将不胜感激:)

我终于找到了解决办法:

想法是创建一个具有特定行为的自定义字符小部件。 JS代码在这里:

odoo.define('cutom_module', function(require)
{
    'use strict';
    var core = require('web.core');
    var Char = core.form_widget_registry.get('char');

    var import_button = Char.extend({
       template : "import_button",
        events : {
           'change' : 'import_files',
        },
        init : function(){
           this._super.apply(this,arguments);
           this._start = null;
        },
        start : function() {
        },
        import_files : function(event){
            var self = this;
            var files = event.target.files; // Get Selected files
            var attachment_ids = self.getParent().fields[ 'attachment_ids' ]; // Get existing attachments
            var data64 = null;
            var values_list = [];
            _.each(files, function(file){
                // Check if the file is already in the attachments, must specify field name here :/
                if(self.already_attached(attachment_ids.get_value(),file.name)){
                    return;
                }
                var filereader = new FileReader();
                filereader.readAsDataURL(file);
                filereader.onloadend = function(upload) {
                        var data = upload.target.result;
                        data64 = data.split(',')[1];
                        var values = {
                            'name' : file.name,
                            'type' : 'binary',
                            'datas' : data64,
                        };
                        values_list.push([ 0, 0, values]);
                        if(values_list.length == files.length){
                            attachment_ids.set_value(values_list);
                        }
                };
            });
        },
        already_attached : function (attachments,filename) {
              for(var i=0;i<attachments.length;i++){
                  if(attachments[i][2]['name'] == filename){
                      return true;
                  }
              }
              return false;
        },
    });

    core.form_widget_registry.add('import_button',import_button);

});

Qweb import_button 模板:

<?xml version="1.0" encoding="UTF-8"?>

<templates xml:space="preserve">
    <t t-name="HiddenInputMultipleFiles">
        <div t-attf-class="oe_hidden_input_file #{fileupload_class or ''}" t-att-style="fileupload_style">
            <form class="o_form_binary_form" t-att-target="fileupload_id"
                  method="post" enctype="multipart/form-data" t-att-action="'/web/binary/upload_attachment'">
                <input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
                <input type="hidden" name="session_id" value="" t-if="widget.session.override_session"/>
                <input type="hidden" name="callback" t-att-value="fileupload_id"/>
                <t t-raw="0"/>
                <input type="file" class="o_form_input_file" name="ufile" t-if="widget.widget!='image'" multiple="multiple"/>
                <input type="file" class="o_form_input_file" name="ufile" accept="image/*" t-if="widget.widget=='image'"/>
            </form>
            <iframe t-att-id="fileupload_id" t-att-name="fileupload_id" style="display: none"/>
        </div>
    </t>

    <div  t-name="import_button" t-attf-class="base #{cls}" class="oe_web_example">
        <p>
            <t t-call="HiddenInputMultipleFiles">

            </t>
        </p>
    </div>
</templates>

查看:

....
<field name="import_files" widget="import_button"/>
<field name="attachment_ids" widget="one2many_list"
                        >
                            <tree create="0">
                                <field name="name" string="File name"/>
                            </tree>
                    </field>
....

和模型:

....
attachment_ids = fields.Many2many(comodel_name="ir.attachment",string="Documents")
import_files = fields.Char(string=" ")
....

如果您有任何问题或改进建议,请告诉我:)

让默认提交处理 1 个文件和额外文件的自定义代码似乎也有效。

openerp.web_natuurpunt_multi_attach = function (session) {
var QWeb = session.web.qweb;
var _t  = session.web._t;

session.web.Sidebar.include({

    on_attachment_changed: function (event) {
        var self = this;
        var session_id = this.session.session_id
        this.$el.find('form.oe_form_binary_form').bind('submit', function (e, data) {
             var form = e.currentTarget;
             var multipleFiles = form.querySelector('input[type=file]');

             if (multipleFiles.files.length > 1) {
                 var callback = form.querySelector('input[name=callback]').defaultValue;
                 var model = form.querySelector('input[name=model]').defaultValue;
                 var id = form.querySelector('input[name=id]').defaultValue
                 const slicedFileList = Object.keys(multipleFiles.files)
                                        .slice(0,multipleFiles.files.length - 1)
                                        .reduce((result, key) => {
                                            result[key] = multipleFiles.files[key];
                                            return result;
                                        }, {});

                 _.each(slicedFileList, function(file){
                     var queryData = new FormData();
                     queryData.append('session_id', session_id);
                     queryData.append('callback', callback);
                     queryData.append('ufile', file);
                     queryData.append('model', model);
                     queryData.append('id', id);
                     var request = new XMLHttpRequest();
                     // do the request using form info
                     request.open(form.method, form.action);
                     // want to distinguish from non-JS submits?
                     request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                     request.send(queryData);
                 });
             }
        });
        self._super(event);
    },
});
}