The import and export of data

Directory structure
|   README.md
|   __init__.py
|   __manifest__.py
+---controllers
|       controllers.py
|       __init__.py 
+---data
|       ir_bills.xml     
+---models
|       order.py
|       __init__.py
+---static     
|   \---src
|       +---img
|       |       default_image.png
|       +---js
|       |       export_xls.js
|       \---xml
|               export_orders.xml          
+---views
|       order.xml
|       templates.xml    
\---wizard
        import_wizard.py
        import_views.xml
        __init__.py    

Export Excel File

oders.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>

        <record model="ir.ui.view" id="export_order_tree_view">
            <field name="name">export_order_tree_view</field>
            <field name="model">l.order</field>
            <field name="arch" type="xml">
                <tree create="0" edit="0" delete="0" import="0" default_order="create_date desc">
                    <field name="name"/>
                    <field name="create_date" string="Order Create Date"/>
                    <field name="customer_id"/>
                    <field name="own_user_id"/>
                    <field name="phone" invisible="1"/>
                    <field name="card_no" invisible="1"/>
                    <field name="data_type"/>
                    <field name="stage_qty"/>
                    <field name="price"/>
                    <field name="service_charge_rate" widget="percentage"/>
                    <field name="service_charge"/>
                    <field name="state" string="Order State"/>
                    <field name="approval_state"/>
                    <field name="note"/>
                </tree>
            </field>
        </record>

        <record model="ir.actions.act_window" id="export_view_action">
            <field name="name">Billing Details</field>
            <field name="res_model">j.order</field>
            <field name="view_type">form</field>
            <field name="view_mode">tree</field>
            <field name="group_id" eval="[(4, ref('module.group_manager'))]"/>
            <field name="search_view_id" ref="order_search_view"/>
            <field name="context">{'search_default_approval_state_2':1}</field>
            <field name="view_ids"
                   eval="[(5, 0, 0),
                   (0, 0, {'view_mode': 'tree', 'view_id': ref('export_order_tree_view')})
                   ]"/>
        </record>

        <menuitem id="export_order_menu" name="Billing Details" parent="main_menu"
                  action="export_view_action" sequence="13"
                  groups="module.group_boss"/>
                  
    </data>
</odoo>
export_orders.xml
<?xml version="1.0" encoding="utf-8"?>
<templates>
    <div t-name="express_extra_buttons" class=" express_extra_buttons">
        <button t-if='widget.model=="j.order" and widget.ViewManager.default_view.fields_view.name=="export_order_tree_view"'
                 type="button" class="btn btn-sm  btn-primary export_xls">
            Export Data
        </button>
    </div>

    <t t-extend="ListView.buttons">
        <t t-jquery="div.o_list_buttons" t-operation="append">
            <t t-call="express_extra_buttons"/>
        </t>
    </t>

    <t t-name="PercentageWidgetHide" t-extend="FieldChar"/>
</templates>
export_xls.js
odoo.define('export_module.export_xls', function (require) {
    'use strict';

    var ListView = require('web.ListView');
    var Model = require('web.Model');
    var framework = require('web.framework');
    var crash_manager = require('web.crash_manager');

    ListView.include({
        render_buttons: function () {
            this._super.apply(this, arguments);
            var self = this;

            // Export data handle
            this.$buttons.on('click', 'button.export_xls', function () {
                var export_columns_string = []; // The field name when export
                var export_columns_names = [];  // The field data when export
                for (var i = 0; i < self.columns.length; i++) {
                    export_columns_string.push(self.columns[i].string);
                    export_columns_names.push(self.columns[i].name)
                }

                var model = new Model(self.model);
                var list_ids = self.groups.get_selection().ids;
                // According to the field query data
                model.query(export_columns_names).filter([['id', 'in', list_ids]]).all().then(function (r) {
                    if (r.length > 0) {
                        var export_rows = [];
                        for (var i = 0; i < r.length; i++) {
                            var rows = []
                            for (var j = 0; j < export_columns_names.length; j++) {
                                rows.push(r[i][export_columns_names[j]])
                            }
                            export_rows.push(rows)
                        }
                    }
                    // Call controllers to download data
                    // console.log(export_columns_string, JSON.stringify(export_rows))
                    console.log(export_columns_string, export_rows);
                    framework.blockUI();
                    self.session.get_file({
                        url: '/export_module/export/xls_data',
                        data: {
                            data: JSON.stringify({
                                model: self.model,
                                headers: export_columns_string,
                                rows: export_rows
                            })
                        },
                        complete: framework.unblockUI,
                        error: crash_manager.rpc_error.bind(crash_manager)
                    });
                });
            });
        }
    });
});
templates.xml
<odoo>
    <data>
        <template id="assets_backend" name="export_module assets" inherit_id="web.assets_backend">
            <xpath expr="." position="inside">
                <script type="text/javascript" src="/export_module/static/src/js/export_xls.js"></script>
                <link rel="stylesheet" href="/export_module/static/src/export_module.less"/>
            </xpath>
        </template>
    </data>
</odoo>
controllers.py
# -*- coding: utf-8 -*-

import json
import xlwt
import operator
from odoo import http
from odoo.http import request
from odoo.addons.web.controllers.main import serialize_exception
from odoo.addons.web.controllers.main import CSVExport, content_disposition, Export, ExcelExport

try:
    from cStringIO import StringIO
except ImportError:
    import cStringIO as StringIO


class ExcelExportView(ExcelExport):
    def __getattribute__(self, name):
        if name == 'fmt':
            raise AttributeError()
        return super(ExcelExportView, self).__getattribute__(name)

    def rows_data_process(self, rows_data):
        if rows_data:
            for row in rows_data:
                for k, v in enumerate(row):
                    if isinstance(v, list):
                        row[k] = v[1]
            return rows_data
        return []

    @http.route('/export_module/export/xls_data', type='http', auth='user')
    def export_xls_data(self, data, token):
        data = json.loads(data)
        model = data.get('model', [])
        columns_headers = data.get('headers', [])
        rows = self.rows_data_process(data.get('rows'))

        return request.make_response(
            self.from_data(columns_headers, rows),
            headers=[
                ('Content-Disposition', 'attachment; filename="%s"'
                 % self.filename(model)),
                ('Content-Type', self.content_type)
            ],
            cookies={'fileToken': token}
        )


class Controller(http.Controller):
    @http.route('/export_module/export/template', type='http', auth="user")
    @serialize_exception
    def download_template(self, data, token):
        params = json.loads(data)
        model, fields = operator.itemgetter('model', 'fields')(params)
        columns_headers = [val['label'].strip() for val in fields]
        return request.make_response(self.from_data(columns_headers),
                                     headers=[('Content-Disposition',
                                               http.content_disposition(model + '.xls')),
                                              ('Content-Type', 'application/vnd.ms-excel')],
                                     cookies={'fileToken': token})

    def from_data(self, fields):
        workbook = xlwt.Workbook()
        worksheet = workbook.add_sheet('Sheet 1')

        for i, fieldname in enumerate(fields):
            worksheet.write(0, i, fieldname)
            worksheet.col(i).width = 4000

        fp = StringIO()
        workbook.save(fp)
        fp.seek(0)
        data = fp.read()
        fp.close()
        return data


Import CSV File

import_wizard.py
# -*- coding: utf-8 -*-

import os
import csv
import base64
import logging

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

from odoo import api, fields, models, tools, _
from odoo.exceptions import except_orm

_logger = logging.getLogger(__name__)


class AlertInfo(except_orm):
    pass


class ImportWizard(models.TransientModel):
    """
    Import customer bills and change orders approval state
    """
    _name = 'import.wizard'

    data = fields.Binary(string=u'文件', required=True)
    filename = fields.Char(string=u'文件名称', required=True)

    @api.multi
    def import_bills(self):
        this = self[0]
        fileformat = os.path.splitext(this.filename)[-1][1:].lower()
        if fileformat != 'csv':
            error = 'CSV files only'
            raise AlertInfo(_("Failed"), error)

        try:
            self._cr.execute('SAVEPOINT ue_import')
            new_data = list(self._read_csv())
            _logger.info('start import')
            self._read_bills(new_data)
        except Exception as e:
            _logger.exception('Import Error')
            self._cr.execute('ROLLBACK TO SAVEPOINT ue_import')
            _logger.info('roll back ue import')
            raise AlertInfo(_("Failed"), tools.ustr(e))
        else:
            self._cr.execute('RELEASE SAVEPOINT ue_import')
            _logger.info("import done")
            return {
                'name': _('Success'),
                'view_type': 'form',
                'view_mode': 'form',
                'view_id': self.env.ref('module_name.import_form_view_success').id,
                'res_model': 'import.wizard',
                'domain': [],
                'context': dict(self._context, active_ids=self.ids),
                'type': 'ir.actions.act_window',
                'target': 'new',
                'res_id': self.id,
            }

    def _read_csv(self):
        csv_data = base64.decodestring(self.data)
        try:
            csv_data = csv_data.decode('utf-8')
        except UnicodeDecodeError:
            csv_data = csv_data.decode('gbk')

        csv_data = csv_data.encode('utf-8')
        csv_iterator = csv.reader(StringIO(csv_data))
        csv_u_iter = ([item.decode('utf-8') for item in row] for row in csv_iterator if
                      any(x for x in row if x.strip()))
        try:
            header = next(csv_u_iter)
        except StopIteration:
            return
        else:
            for line in csv_u_iter:
                yield dict(zip(header, line))

    def _read_bills(self, new_data):
        for data in new_data:
            import_name = data.get(u'订单号', '')
            customer_order_obj = self.env['customer.order'].search([('name', '=', import_name)])

            if customer_order_obj.state == 'done':
                approval_state = data.get(u'审批状态')

                if approval_state == u'成功' or approval_state == '1':
                    selection = '1'
                else:
                    selection = '0'

                customer_order_obj.write({'approval_state': selection})

import_views.xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>

        <record id="import_form_view" model="ir.ui.view">
            <field name="name">Import Bills Change Status</field>
            <field name="model">import.wizard</field>
            <field name="arch" type="xml">
                <form>
                    <div>
                        <div>
                            <div>注意:</div>
                            <div style="margin-left:20px">1.下载模板,并按模板数据格式填写数据.</div>
                            <div style="margin-left:20px">2.不允许修改模板文件的后缀名以及标题.</div>
                        </div>
                    </div>
                    <div style="margin-top:50px">
                        <a href='/module_name/download_models/template_csv' target='_blank'>下载模板</a>
                    </div>
                    <group>
                        <group>
                            <field name="data" filename="filename"/>
                            <field name="filename" invisible="1"/>
                        </group>
                    </group>

                    <footer>
                        <button name="import_bills" string="导入" type="object" class="btn-primary"/>
                        <button string="取消" class="btn-default" special="cancel"/>
                    </footer>
                </form>
            </field>
        </record>


        <record id="bills_import_action" model="ir.actions.act_window">
            <field name="name">Import Bills</field>
            <field name="type">ir.actions.act_window</field>
            <field name="res_model">import.wizard</field>
            <field name="view_type">form</field>
            <field name="view_mode">form</field>
            <field name="view_id" ref="import_form_view"/>
            <field name="target">new</field>
        </record>


        <menuitem id="import_bills_menu" name="Import Bills" parent="module_name.main_menu"
                  action="bills_import_action" sequence="15"
                  groups="module_name.group_boss"/>


        <record id="import_form_view_success" model="ir.ui.view">
            <field name="name">Import Bills Change Status Success</field>
            <field name="model">import.wizard</field>
            <field name="arch" type="xml">
                <form>
                    <group colspan="4">
                        <label string="导入成功"/>
                    </group>
                    <footer>
                        <button special="cancel" string="关闭" class="btn-primary"/>
                    </footer>
                </form>
            </field>
        </record>

    </data>
</odoo>
ir_bills.xml
<odoo>
    <data>

        <record id="import_bills_template" model="ir.exports">
            <field name="name">Results the template for approval of the bills</field>
            <field name="resource">customer.order</field>
        </record>


        <record id="import_bill_field_1" model="ir.exports.line">
            <field name="name">name</field>
            <field name="export_id" ref="import_bills_template"/>
        </record>

        <record id="import_bill_field_2" model="ir.exports.line">
            <field name="name">customer_id</field>
            <field name="export_id" ref="import_bills_template"/>
        </record>

        <record id="import_bill_field_3" model="ir.exports.line">
            <field name="name">approval_state</field>
            <field name="export_id" ref="import_bills_template"/>
        </record>

    </data>
</odoo>

controllers.py
# -*- coding: utf-8 -*-

from odoo.http import request
from odoo import http
from odoo.addons.web.controllers.main import CSVExport, content_disposition, Export, ExcelExport


class DownloadModels(http.Controller):

    @http.route('/module_name/download_models/template_csv', auth='public', csrf=False)
    def bill_template_csv(self):
        """
        Download customer bill template file
        """
        records = request.env['j.order'].search([], limit=3)
        name_list = Export().namelist('j.order', request.env.ref('module_name.import_bills_template').sudo().id)
        field_names = [i['name'] for i in name_list]
        field_labels = [i['label'] for i in name_list]
        data = records.export_data(field_names).get('datas', [])
        d = CSVExport().from_data(field_labels, data)
        return http.Response(d, headers=[('Content-Disposition', content_disposition('bills_info.csv')),
                                         ('Content-Type', 'application/vnd.ms-excel')])

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • # Awesome Python [![Awesome](https://cdn.rawgit.com/sindr...
    emily_007阅读 2,212评论 0 3
  • 1.创建文件夹 !/bin/sh mkdir -m 777 "%%1" 2.创建文件 !/bin/sh touch...
    BigJeffWang阅读 10,072评论 3 53
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,672评论 18 139
  • .窗外,雨滴轻敲着窗棂 黑暗中,我怎么又睁大了眼睛 我的心怎么又开始隐隐作痛 怎么又有泪水划过脸颊轻轻 我知道我又...
    Aayue阅读 390评论 9 3
  • 我从小学到初高中然后到大学我平淡无奇,默默的喜欢一个人,默默的做着无聊的事。身边朋友不少但总感觉少了点什么,也许...
    司马权阅读 544评论 0 0