Web forms serve as a valuable tool for gathering user information, encompassing contact details, educational background, career history, and more. Moreover, they are instrumental in conducting surveys effectively. Web forms allow for the creation of various field types, aiding in the systematic collection of data. Among these, the attachment field stands out. In this article, we’ll explore the process of establishing an attachment field to store uploaded files from web forms in Odoo 16.
To begin, we must create a field in our model to accommodate attachments. Odoo provides a model called ‘ir.attachment’ for managing attachment files. In our case, we’ve inherited the ‘res.partner’ model to incorporate the attachment field:
attachment_ids = fields.Many2many('ir.attachment', string='Attachments')
ir.attachment’ is Odoo’s designated model for storing attachments submitted by end users. In this guide, we will illustrate how to utilize this model to upload files via web forms.
To implement our web form, we need to craft an XML file. Within this file, insert the ‘form’ tag and define the fields you wish to include. The attachment input field can be placed anywhere within this form. Below is an example featuring various fields, including the attachment field. Incorporate this field within the ‘form’ tag. The ‘form’ tag comes with several attributes such as ‘class,’ ‘action,’ ‘method,’ ‘enctype,’ etc. Notably, the ‘enctype’ attribute plays a crucial role when dealing with attachments. It specifies that the characters in the file should not be encoded. Here’s a ‘form’ tag example with the ‘enctype’ attribute:
<form action="/my/account" method="post"
enctype="multipart/form-data">
<div class="row o_portal_details">
<div class="col-lg-8">
<div class="row">
<t t-call="portal.portal_my_details_fields"/>
<div t-attf-class="mb-3 #{error.get('name') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="attachment">
Attach file
</label>
<input type="file"
name="att"
accept=".pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
required="required"/>
</div>
<input type="hidden" name="redirect"
t-att-value="redirect"/>
</div>
<div class="clearfix">
<button type="submit"
class="btn btn-primary float-end mb32 ">
Confirm
<span class="fa fa-long-arrow-right"/>
</button>
</div>
</div>
</div>
</form>
In the controller, you must develop a function to encode the file and save it to the database. Here’s a sample code snippet:
import base64
from odoo.addons.portal.controllers.portal import CustomerPortal
from odoo.http import request, route
class ResPartnerController(CustomerPortal):
@route(['/my/account'], type='http', auth='public', website=True)
def account(self, redirect=None, **post):
res = super().account()
partner_id = request.env.user.partner_id
Attachment = request.env['ir.attachment']
file = post.get('attachment')
attachment_id = Attachment.create({
'name': file.file_name,
'type': 'binary',
'datas': base64.encodebytes(file.read()),
'res_model': partner_id._name,
'res_id': partner_id.id
})
partner_id.update({
'attachment': [(4, attachment_id.id)],
})
return res
The line ‘base64.b64encode(file.read())’ encodes the content of the uploaded file. It reads the file content until it encounters an empty string, returning the encoded data along with a trailing newline character (‘n’). As a result, the file is stored in the database, demonstrating how to upload files via web forms.
To read more about uploading files from web form in the Odoo 15, refer to our blog How to Upload Files From Web Form in the Odoo 15