odoo 后台与前端文件(附件)存储与下载实现

笔记太多了很乱,想想还是写博客的好,慢慢更

当然了,前提是你已经配好了odoo开发环境


一、odoo后台界面实现附件的上传和下载

1)、在应用中搜索下图组件,安装

成功后,随便打开一个form视图就能看到上面多了一个附件按钮,点击即可上传

2)、在你的模型中加入一个关联到这个附件模型的字段

information_attachment = fields.Many2many('ir.attachment', compute='_get_attachment_ids', string=u'附件')

这里使用的是Many2many进行关联

ir.attachment 就是上图安装的模块Attachments……的模型的_name,这是odoo本身自带的附件模型功能,odoo后台上传的所有附件都会存到这个模型的数据库表里
compute :根据所属的模型和实例获取附件

既然如此,所有的附件都存在同一个模型中,如何知道那些附件是由哪个模型中的哪个实例上传的呢?

我们先来看看数据库中ir.attachement的表

字段太多了不一一解释

res_model: 定义的模型名

res_id:模型名实例化的对象id

有个这两个字段,我们就能取到对应模型对面的特例(实例化对象)

_get_attachment_ids方法就是用来获取附件

     def _get_attachment_ids(self):
att_model = self.env['ir.attachment'] #获取附件模型
for obj in self:
query = [('res_model', '=', self._name), ('res_id', '=', obj.id)] #根据res_model和res_id查询附件
obj.information_attachment = att_model.search(query) #取得附件list

根据上面代码取得附件,便可以显示出来了。

3)、值得一提的是:

<field name="information_attachment" widget="many2many_binary"/>

在form视图xml文件中指定widget为 “many2many_binary”,则会如下图显示,更加直观

点击相应的附件,即可下载。


一点都不可爱的分割线


二、前端请求服务器,获取附件

odoo后台实现了附件的上传和下载,那我的前端页面要怎么获取它呢?

换句话说,我的controller要怎么写呢?

1)、首先,前端取得你要获取附件的res_model和res_id,传回给后台附件id。

根据前面的讲解,根据这两个字段可以取到一个附件list,要取得特定的附件,我还需要一个附件id

attachment_id = request.env['ir.attachment'].sudo().search_read(
[('res_model', '=', 'em.council.information'), ('res_id', '=', task_id)],
["name", "id"]

这段代码,是在controller根据模型的res_model和res_id取得附件list,我存下了以下两个字段:

name : 就是附件的名字  #用于前端的展示,给用户显示附件名称
id:每个附件有一个特定的id #唯一标示,在数据库中查询附件用

然后给前端返回去,至于怎么取到数据,就看你喜欢了,我用的是jinja2,ajax也可以

如果是jinjia2,就返回

return template.render(data=attachment_id)

如果是ajax,自然就是

Response(json.dumps(attachment_id), 200)

然后你自己在前端中把他们渲染出来展示给用户

2)、用户点击相应附件,实现下载

用户点击了附件,我们有一个附件id,我们这里叫attachment_id,跟前面的attachment_id[1]存的id是一个东西

 function onReturnAttachment_id(attachment_id) {
window.location.href = 'http://localhost:8069/w/download?attachment_id=' + attachment_id
}

为了方便讲解,前端偷懒直接用了跳转,请你不要偷懒,写一个阿贾克斯。

上面的跳转已经暴露了我的路由是

w/download

然后传回了attachment_id给controller,接下来就是:

1、controller取得attachment_id

2、controller根据attachment_id查询数据库找到相应的附件

3、controller给前端返回附件

直接上代码:

 @http.route('/w/download', type='http', auth='public', csrf=False)
def w_download_attachment(self, **kwargs):
attachment_id = kwargs.get('attachment_id')
attachment = request.env['ir.attachment'].sudo().search_read(
[('id', '=', int(attachment_id))],
["name", "datas", "res_model", "res_id", "type", "url"]
)
if attachment:
attachment = attachment[0]
else:
return redirect('/w/download') res_id = attachment['res_id']
if attachment["type"] == "url":
if attachment["url"]:
return redirect(attachment["url"])
else:
return request.not_found()
elif attachment["datas"]:
data = StringIO(base64.standard_b64decode(attachment["datas"]))
return http.send_file(data, filename=attachment['name'], as_attachment=True)
else:
return request.not_found()

稍微解释一下:

attachment_id = kwargs.get('attachment_id') #取得前端传回来的id
#根据id取得数据库中对应的附件,其中datas就是我们的附件数据
attachment = request.env['ir.attachment'].sudo().search_read(
[('id', '=', int(attachment_id))],
["name", "datas", "res_model", "res_id", "type", "url"]
)

判断一下有没有取到,取到了又因为search_read返回一个list,但应该只有一条数据,因此 attachment = attachment[0]

        if attachment:
attachment = attachment[0]
else:
return redirect('/w/download')

1)、判断一下是不是存的url,是的话重定向

2)、如果不是url存的,取得datas,base64解码一下存到data

3)、把data和文件名打包返回给前端

         if attachment["type"] == "url":
if attachment["url"]:
return redirect(attachment["url"])
else:
return request.not_found()
elif attachment["datas"]:
data = StringIO(base64.standard_b64decode(attachment["datas"]))
return http.send_file(data, filename=attachment['name'], as_attachment=True)
else:
return request.not_found()

此时前端访问前面给的url便能下载对应附件了,比如我要下载前面存的附件中的“收藏的前端资料网址”,我理论上访问的是

http://localhost:8069/w/download?attachment_id=266

三、前端上传附件存到数据库中

这个记录一下思路,其实就是一个逆过程,自己尝试一下

1、拿到必要的字段,如res_model和res_id,你要存入附件的datas(base64编码格式)
2、将数据传回controller
3、controller处理数据,并操作数据库create一条记录

浅谈odoo 后台与前端文件(附件)的存储与下载的更多相关文章

  1. 浅谈Linux下/etc/passwd文件

    浅谈Linux 下/etc/passwd文件 看过了很多渗透测试的文章,发现在很多文章中都会有/etc/passwd这个文件,那么,这个文件中到底有些什么内容呢?下面我们来详细的介绍一下. 在Linu ...

  2. 浅谈WEB安全性(前端向)

    相信进来的时候你已经看到alert弹窗,显示的是你cookie信息(为配合博客园要求已删除).单纯地在你的客户端弹出信息只是类似于迫使你在自己的房间脱衣服——没人看得到,自然也不算啥恶意行为.那么如果 ...

  3. 三分钟浅谈TT猫的前端优化

    首先看一张访问TT猫首页的截图: 测试环境为谷歌浏览器,暂且不讨论其它浏览器,截图下方我们可以观察到以下参数: DOMContentLoaded:1.42s | Load:2.31s 以上参数是在CT ...

  4. 浅谈2D游戏设计模式2- WZ文件详解(UI.WZ)之MapLogin.img(1)

    玩过冒险岛的人都知道有一个WZ文件,那么这个WZ文件的内部是怎么样的呢,今天我就带大家一探究竟. 说实在的,我这是第一次接触WZ文件,但是却让我很震撼,为什么很震撼,因为这个居然是用VS2010写的! ...

  5. 浅谈Oracle中物理结构(数据文件等。。。)与逻辑结构(表空间等。。。。。)

    初始Oracle时很难理解其中的物理结构和逻辑结构,不明白内存中和硬盘中文件的区别和联系,我也是初学Oracle,这里就简单的谈谈我我看法. 首先,你需要明白的一点是:数据库的物理结构是由数据库的操作 ...

  6. 浅谈hadoop中mapreduce的文件分发

    近期在做数据分析的时候.须要在mapreduce中调用c语言写的接口.此时就须要把动态链接库so文件分发到hadoop的各个节点上,原来想自己来做这个分发,大概过程就是把so文件放在hdfs上面,然后 ...

  7. 浅谈JVM编译原理->.java文件转变为.class文件的过程

    为什么需要编译? 我们平常写代码,有规范的命名方式,都能够看得懂,但是我们写的代码计算机是看不懂的,所以需要编译,也就是一个转换的过程,如下: 1.这个是咱们平时写的代码,就比较好理解,对人友好 2. ...

  8. 浅谈linux系统中pdf文件的默认打开方式

    atril.gimp和evince,三者均可以打开application/pdf格式文件.gimp为一款图像处理软件:atril为mate环境下常用的文档查看器:evince为gnome环境下常用的文 ...

  9. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

随机推荐

  1. 使用Ansible进行项目的自动部署(Tomcat、Weblogic)

    原文:https://github.com/x113773/testall/issues/4 问题:Weblogic/Tomcat 通过JAVA直接远程调用或者调用本地Shell还是通过Ansible ...

  2. java的三大特性,封装,继承,多态

    封装 /** * 所谓封装,就是将对象具有的成员变量和成员函数包装和隐藏起来,让外界无法直接使用, * 被封装的成员只能通过某些特定的方式才能访问. * 实现封装有两个步骤: *   1.将不能暴露的 ...

  3. phpcmsV9常用标签

    头部: <title>{if isset($SEO['title']) && !empty($SEO['title'])}{$SEO['title']}{/if}{$SEO ...

  4. 巧用五招提升Discuz!X运行速度

    Discuz!X使用的是数据库应用程序,所以,当数据库的大小.帖子的数目.会员的数目,这些因素都会影响到程序的检索速度,尤其是当论坛的影响力大了,这个问题就更为突出了,虽然,康盛对Discuz进行了更 ...

  5. 手机app微信支付后台处理流程

    第一步:客户在手机app确认订单,提交订单后,app将订单详情传给后台,后台将订单存入数据库,将存入数据库的id返回给app. 第二步:这时候手机端app会让客户选择哪种付款方式,我们做的是微信,所以 ...

  6. Android高仿qq及微信底部菜单的几种实现方式

    最近项目没那么忙,想着开发app的话,有很多都是重复,既然是重复的,那就没有必要每次都去写,所以就想着写一个app通用的基本框架,这里说的框架不是什么MVC,MVP,MVVM这种,而是app开发的通用 ...

  7. Vijos 1034 家族 并查集

    描述 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚.如果x,y是亲戚 ...

  8. 怎样禁止手机app 中页面有时候会把数字当做电话号码,从而自动进行打电话功能

    想要禁止这种功能,只需要给头不加一个meta标签就可以了, <meta name="format-detection" content="telephone=no& ...

  9. JQuery中常用的选择器

    属性选择器 1>  [attribute] 概述:匹配包含给定属性的元素. 示例 jQuery 代码:$("div[id]") 描述:查找所有含有 id 属性的 div 元素 ...

  10. Java 反射在实际开发中的应用

    运行时类型识别(RTTI, Run-Time Type Information)是Java中非常有用的机制,在java中,有两种RTTI的方式,一种是传统的,即假设在编译时已经知道了所有的类型:还有一 ...