Odoo前端附件无法同步至后端问题求助
问题排查与解决方案
核心问题原因
- 前端请求方式错误:使用
ajax.jsonRpc传递FormData是无效的——jsonRpc会自动将参数序列化为JSON格式,而FormData无法被JSON序列化,导致文件数据根本没传到后端。 - 后端路由类型不匹配:路由设置为
type='json'时,Odoo不会解析multipart/form-data格式请求中的文件,request.httprequest.files始终为空。 - 参数传递逻辑混乱:前端将普通字段与
FormData分开传递,后端无法同时接收两种格式的参数。
修正方案
1. 前端代码调整
改用ajax.post发送multipart/form-data请求,将所有字段(文本+文件)统一放入FormData:
odoo.define('test_payment.payment', function(require) { "use strict"; var ajax = require('web.ajax'); $(document).ready(function() { 'use strict'; $('button[name="o_payment_submit_button"]').bind("click", function(ev) { ev.preventDefault(); // 阻止按钮默认提交行为,避免页面跳转 var formData = new FormData(); // 添加文本字段 formData.append('comment', $('#customer_comment').val()); formData.append('client_order_ref', $('#customer_po').val()); // 添加文件字段 var files = $('#customer_documents')[0].files; for (var i = 0; i < files.length; i++) { formData.append('customer_documents', files[i]); } // 发送multipart请求 ajax.post('/shop/customer_comment', formData, { contentType: false, processData: false, }).then(function(res) { console.log('数据提交成功:', res); // 这里可以继续执行原有的支付流程 }).fail(function(err) { console.error('提交失败:', err); }); }); }); });
2. 后端代码调整
修改路由类型为http,适配multipart/form-data请求,同时修正附件存储的编码逻辑:
"""Add Customer comment functions to the website_sale controller.""" from odoo import http from odoo.http import request class WebsiteSale(http.Controller): @http.route(['/shop/customer_comment'], type='http', auth="public", methods=['POST'], website=True, csrf=True) def customer_comment(self, **post): """Add comment and attachments to sale order when clicking 'pay now'""" comment = post.get('comment') client_order_ref = post.get('client_order_ref') if comment: order = request.website.sale_get_order() redirection = self.checkout_redirection(order) if redirection: return redirection if order and order.id: # 更新订单文本字段 order.write({ 'customer_comment': comment, 'client_order_ref': client_order_ref, }) # 处理上传文件 customer_documents = request.httprequest.files.getlist('customer_documents') attachment_ids = [] for doc in customer_documents: if doc.filename: # 跳过空文件 attachment_data = { 'name': doc.filename, 'type': 'binary', 'res_model': 'sale.order', 'res_id': order.id, 'datas': doc.read().encode('base64'), # Odoo要求附件数据为base64编码 'mimetype': doc.content_type, } attachment = request.env['ir.attachment'].sudo().create(attachment_data) attachment_ids.append(attachment.id) # 有附件才发送消息 if attachment_ids: order.message_post(attachment_ids=attachment_ids) # 返回JSON格式响应 return request.make_json_response({'success': True})
关键说明
- 前端必须用
ajax.post而非jsonRpc,因为jsonRpc仅支持JSON格式参数,无法处理文件上传。 - 后端路由
type改为http后,Odoo会自动解析multipart/form-data中的表单字段和文件。 ir.attachment的datas字段要求存储base64编码的二进制数据,所以需要对文件内容做encode('base64')处理。- 添加
csrf=True是Odoo网站路由的安全规范,避免跨站请求伪造。
内容的提问来源于stack exchange,提问作者Bishal Ghimire
相关产品推荐
相关产品推荐

