一.附件上传

这里收集了三种附件上传方式:

1.odoo自带附件上传

安装odoo自带的附件列出及文档模块

这样在编辑界面就可以看到附件上传按钮了(odoo14自己测试没成功,暂时不知道原因)

2. 后端代码实现附件上传(一)

model类中添加以下代码

attachment_count = fields.Integer(compute='_compute_attachment_count', string='附件数量', required=True)def _compute_attachment_count(self):# 附件数量计算attachment_data = self.env['ir.attachment'].read_group([('res_model', '=', 'supplier.management'), ('res_id', 'in', self.ids)], ['res_id'], ['res_id'])attachment = dict((data['res_id'], data['res_id_count']) for data in attachment_data)for expense in self:expense.attachment_count = attachment.get(expense.id, 0)def action_get_attachment_view(self):"""附件上传 动作视图"""self.ensure_one()# domain可以过滤指定的附件类型 (mimetype)domain = [('res_model', '=', self._name), ('res_id', '=', self.id)]return {'domain': domain,'res_model': 'ir.attachment','name': u'附件管理','type': 'ir.actions.act_window','view_id': False,'view_mode': 'kanban,tree,form','view_type': 'form','limit': 20,'context': "{'default_res_model': '%s','default_res_id': %d}" % (self._name, self.id)}

xml文件添加以下代码

<button name="action_get_attachment_view" class="oe_stat_button" icon="fa-book" type="object"><div class="o_stat_info"><span class="o_stat_text">附件上传</span><field name="attachment_count"/></div>
</button>

form视图界面就会出现附件上传的按钮

3. 后端代码实现附件上传(二)

model类中添加以下代码

attachment_ids = fields.Many2many('ir.attachment', relation="ir_attachment_attachment_ref", string='附件')

xml文件添加以下代码

<notebook><page string="附件"><field name="attachment_ids" widget="many2many_binary" /></page>
</notebook>

form视图界面显示

二.附件预览widget(图片与pdf)

功能代码实现参考:https://www.programminghunter.com/article/81071420050/

效果描述:

  • 1.当点击图片或者文件时展开图片。
  • 2.当点击关闭按钮时关闭图片预览。
  • 3.当点击下载按钮时,下载文件。

缺点:

  • 当预览图片大小超过1000px的时候,不会动态变小;
  • 点击查看一个文件,当点击另一个文件时,上一个文件不会自动关闭。

使用方法:在form视图中使用widget="many2many_preview_pdf",示例代码

<field name="attachment_info_ids" widget="many2many_preview_pdf" />

预览效果图

预览模块下载链接:https://pan.baidu.com/s/1D-zssmy9_JKOKu5qR0ThvA?pwd=r9bm 
提取码:r9bm

文件预览代码实现:

1.编写js文件代码:/static/src/js/file_preview.js

odoo.define("many2many_preview_pdf", function (require) {"use strict";var AbstractField = require("web.AbstractField");var field_registry = require("web.field_registry");var core = require('web.core');var qweb = core.qweb;var many2many_preview_pdf = AbstractField.extend({template: "FieldBinaryFileUploader",template_files: "PdcDocument.files",supportedFieldTypes: ['many2many'],fieldsToFetch: {name: { type: 'char' },mimetype: { type: 'char' },},events: {'click .o_attach': '_onAttach','click .o_attachment_delete': '_onDelete','change .o_input_file': '_onFileChanged','click .o_image_box': '_onFilePDF','click .pdc_close' : '_onclosePDF',},/*** @constructor*/init: function () {this._super.apply(this, arguments);if (this.field.type !== 'many2many' || this.field.relation !== 'ir.attachment') {var msg = _t("The type of the field '%s' must be a many2many field with a relation to 'ir.attachment' model.");throw _.str.sprintf(msg, this.field.string);}this.uploadedFiles = {};this.uploadingFiles = [];this.fileupload_id = _.uniqueId('oe_fileupload_temp');$(window).on(this.fileupload_id, this._onFileLoaded.bind(this));this.metadata = {};},destroy: function () {this._super();$(window).off(this.fileupload_id);},//--------------------------------------------------------------------------// Private//--------------------------------------------------------------------------_getFileId: function (attachment) {return attachment.id},_getId: function (attachment) {return attachment.attributes[1].value},_generatedMetadata: function () {var self = this;_.each(this.value.data, function (record) {// tagging `allowUnlink` ascertains if the attachment was user// uploaded or was an existing or system generated attachmentself.metadata[record.id] = {allowUnlink: self.uploadedFiles[record.data.id] || false,FileId: self._getFileId(record.data)};});},_render: function () {// render the attachments ; as the attachments will changes after each// _setValue, we put the rendering here to ensure they will be updatedconsole.log("test123");this._generatedMetadata();this.$('.oe_placeholder_files, .o_attachments').replaceWith($(qweb.render(this.template_files, {widget: this,})));this.$('.oe_fileupload').show();// display image thumbnailthis.$('.o_image[data-mimetype^="image"]').each(function () {var $img = $(this);if (/gif|jpe|jpg|png/.test($img.data('mimetype')) && $img.data('src')) {$img.css('background-image', "url('" + $img.data('src') + "')");}});},_onAttach: function () {// This widget uses a hidden form to upload files. Clicking on 'Attach'// will simulate a click on the related input.this.$('.o_input_file').click();},_onclosePDF: function () {console.log(this.$el.find('.zPDF_iframe').remove());console.log('111111');},_onDelete: function (ev) {ev.preventDefault();ev.stopPropagation();var fileID = $(ev.currentTarget).data('id');var record = _.findWhere(this.value.data, { res_id: fileID });if (record) {this._setValue({operation: 'FORGET',ids: [record.id],});var metadata = this.metadata[record.id];if (!metadata || metadata.allowUnlink) {this._rpc({model: 'ir.attachment',method: 'unlink',args: [record.res_id],});}}},_onFileChanged: function (ev) {var self = this;ev.stopPropagation();var files = ev.target.files;var attachment_ids = this.value.res_ids;// Don't create an attachment if the upload window is cancelled.if (files.length === 0)return;_.each(files, function (file) {var record = _.find(self.value.data, function (attachment) {return attachment.data.name === file.name;});if (record) {var metadata = self.metadata[record.id];if (!metadata || metadata.allowUnlink) {// there is a existing attachment with the same name so we// replace itattachment_ids = _.without(attachment_ids, record.res_id);self._rpc({model: 'ir.attachment',method: 'unlink',args: [record.res_id],});}}self.uploadingFiles.push(file);});this._setValue({operation: 'REPLACE_WITH',ids: attachment_ids,});this.$('form.o_form_binary_form').submit();this.$('.oe_fileupload').hide();ev.target.value = "";},_onFileLoaded: function () {var self = this;// the first argument isn't a file but the jQuery.Eventvar files = Array.prototype.slice.call(arguments, 1);// files has been uploaded, clear uploadingthis.uploadingFiles = [];var attachment_ids = this.value.res_ids;_.each(files, function (file) {if (file.error) {self.do_warn(_t('Uploading Error'), file.error);} else {attachment_ids.push(file.id);self.uploadedFiles[file.id] = true;}});this._setValue({operation: 'REPLACE_WITH',ids: attachment_ids,});},_onFilePDF: function (ev) {var self = this;var fieldId = self._getId(ev.currentTarget);self.$el.append(`<div class="zPDF_iframe"><div class="pdc_close btn btn-primary">关闭</div>&nbsp;&nbsp;&nbsp;<div class="btn btn-primary"><a href="/web/content/${fieldId}?download=true" style="text-decoration: none; color: white">下载</a></div><br><iframe  class="zPDF" scrolling="no" id="main" name="main" frameborder="0"  style="min-height:600px;width:1000px;height:100%;" src="/web/content/${fieldId}"></iframe></div>`)}});field_registry.add("many2many_preview_pdf", many2many_preview_pdf);return many2many_preview_pdf
});

2. 导入js文件

创建xml文件导入js:/views/import_src_js.xml

<?xml version="1.0" encoding="utf-8"?>
<odoo><template id="assets_backend" name="file_preview_tpl" inherit_id="web.assets_backend"><xpath expr="." position="inside"><script type="text/javascript" src="/file_preview/static/src/js/file_preview.js" /></xpath></template>
</odoo>

3. 创建widget的qweb模板:/static/src/xml/base.xml

<?xml version="1.0" encoding="UTF-8" ?>
<template><div t-name="PdcDocument.files" class="o_attachments" aria-atomic="true"><!-- uploaded files --><t t-foreach="widget.value.data" t-as="file"><t t-if="!file.data.upload" t-call="PdcDocument.attachment_preview"/></t><!-- uploading files --><t t-foreach="widget.uploadingFiles" t-as="file"><t t-set="upload" t-value="true"/><t t-call="PdcDocument.attachment_preview"/></t></div><t t-name="PdcDocument.attachment_preview"><t t-set="url" t-value="widget.metadata[file.id] ? widget.metadata[file.id].url : false"/><t t-if="file.data" t-set="file" t-value="file.data"/><t t-set="editable" t-value="widget.mode === 'edit'"/><t t-if="file.mimetype" t-set="mimetype" t-value="file.mimetype"/><div t-attf-class="o_attachment o_attachment_many2many #{ editable ? 'o_attachment_editable' : '' } #{upload ? 'o_attachment_uploading' : ''}"t-att-title="file.name"><div class="o_attachment_wrap"><t t-set="ext" t-value="file.name.replace(/^.*\./, '')"/><div class="o_image_box float-left" t-att-data-id="file.id"><div t-att-title="'Download ' + file.name" aria-label="Download"><span class="o_image o_hover" t-att-data-id="FileId" t-att-data-mimetype="mimetype"t-att-data-ext="ext" role="img"/></div></div><div class="caption"><a class="ml4" t-att-href="url" t-att-title="'Download ' + file.name"><t t-esc='file.name'/></a></div><div class="caption small"><div class="ml4 small text-uppercase" t-att-title="'Download ' + file.name"><b><t t-esc='ext'/></b></div><div t-if="editable" class="progress o_attachment_progress_bar"><div class="progress-bar progress-bar-striped active" style="width: 100%">Uploading</div></div></div><div t-if="editable" class="o_attachment_uploaded"><i class="text-success fa fa-check" role="img" aria-label="Uploaded" title="Uploaded"/></div><div t-if="editable" class="o_attachment_delete" t-att-data-id="file.id"><span class="text-white" role="img" aria-label="Delete" title="Delete">×</span></div></div></div></t>
</template>

同时,记得在__mainfest__.py文件中引入上述文件

    'data': ['views/import_src_js.xml',],'qweb': ["static/src/xml/base.xml"],

至此,即可在odoo中完成一个自定义widget,接下来只要使用定义的widget即可。

odoo14 ir.attachment附件上传与附件预览功能相关推荐

  1. iOS学习:调用相机,选择图片上传,带预览功能

    iOS学习:调用相机,选择图片上传,带预览功能 发表于2年前(2013-05-30 21:38)   阅读( 18194) | 评论( 16) 27人收藏此文章,我要收藏 赞3 8月22日珠海 OSC ...

  2. 用openoffice+jodconverter+webuploader+pdf.js实现文件上传、在线预览功能

    一.背景 最近公司一个项目要实现一个文件上传以及多文档在线预览的功能,之前一直做无线工具开发的,没有涉及到这些东西.另外项目组缺java开发人员,而且自己也只是一个半吊子前端加小半吊子java开发人员 ...

  3. php上传头像的代码,php实现文件上传及头像预览功能

    php文件上传原理是通过form表单的enctype="multipart/form-data"属性将文件临时放到wamp文件夹中的tmp目录下,再通过后台php程序将文件保存在体 ...

  4. 2016/4/19 ①单个文件上传 ②上传图片后 预览图片

    1,f1.php <!DOCTYPE html> <htmllang="en"> <head><metacharset="UTF ...

  5. js上传视频,预览视频

    js上传视频,预览视频 <videostyle="width:300px; height:auto;object-fit: fill;"playsinlinecontrols ...

  6. html上传头像及预览,js实现头像上传并且可预览提交

    在用户注册账号或者修改资料的时候会需要用户在本地选择一张图片作为头像,并同时预览, 常见的思路有两种:一是将图片上传至服务器的临时文件夹中,并返回该图片的url,然后渲染在html页面:另一种思路是, ...

  7. JavaScript 实现图片上传前本地预览

    JavaScript 实现图片上传前本地预览 图片上传前预览,应该算是一个普遍的需求,很多时候可能选中的图片并不是想要的那张,所以需要上传前预览下. JS(浏览器中)是一门特殊的语言,它没有直接读写磁 ...

  8. struts上传word和excel文件到oracle,Struts文件上传,下载,重传,预览

    [Struts2]☆★之文件上传,下载,重传,预览 今日群里一兄弟问我能否给一份struts文件上传下载的例子,因为自己项目比较紧所以想在网上找 些源码给他,但是纵观全网,写的都不是太全,这让新手使用 ...

  9. 微信小程序云开发实现上传文件和预览下载文件

    微信小程序云开发实现上传文件和预览下载文件 一.前言 目前微信提供了一个接口 wx.chooseMessageFile 它能让用户从聊天记录里面选择一个或者多个文件,然后返回它的一些信息,列入文件的p ...

  10. PHP上传文件并预览

    达到上传文件并预览效果主要是一下代码: <h4>文件信息</h4> <?php if ($_SERVER["REQUEST_METHOD"] == & ...

最新文章

  1. R语言合并两个或多个有序数dataframe实战(dataframe的纵向合并):使用R原生方法、data.table、dplyr等方案
  2. C#中的参数传递(转)
  3. AWS — AWS CloudFormation
  4. 华为mstp多生成树配置_【交换机】交换机如何配置MSTP(多实例生成树协议)
  5. .net mysql 特殊字符转义字符_MySQL 特殊字符转义问题
  6. Linux找最大最小值的命令,Linux中awk命令正确的求最大值、最小值、平均值、总和...
  7. mysql多主单向环形_mysql多主单向--gt;环形同步_MySQL
  8. C#中IEnumerableT.Join()和IEnumerableT.GroupJoin()简单使用
  9. LeetCode —— 365. 水壶问题(Python3)
  10. 重磅更新!YoloV4最新论文!解读yolov4框架
  11. Python项目生成requirements.txt的多种方式
  12. python文件和路径操作
  13. python小明爬楼梯_爬楼梯(Python and C++解法)
  14. 阶段5 3.微服务项目【学成在线】_day01 搭建环境 CMS服务端开发_13-MongoDb入门-数据库和集合...
  15. Android TableLayout 表格布局详解
  16. 使用Advanced Installer打包安装程序
  17. 新建了个文件写代码报 Delete `␍`
  18. C#-实现微信激活会员卡后响应激活动作并获取会员信息
  19. 教育行业运维审计用什么堡垒机好?有什么作用?
  20. python机器人库(robotics-toolbox-python)的运用

热门文章

  1. 如何快速搭建线上电商商城网站?
  2. 使用CSS画一个三角形
  3. RDF和SPARQL
  4. Citrix 服务器虚拟化之三十二 XenConvert
  5. 关于产品的一些思考——阿里巴巴之来往
  6. 树莓派:10行代码体验红外检测
  7. Effective java 总结11 - 序列化
  8. 新中新SDK 身份证代码编写
  9. 华为AC+AP普通配置
  10. 【yum】常见的yum命令