A web form is an essential component of digital interaction that allows users to submit data. It serves as a key feature in web applications, enabling communication between users and websites by collecting information efficiently. Many web forms include a dedicated file upload section, enabling users to attach documents, images, or other digital files. This practical feature simplifies document submission without requiring external sharing methods. Next, we'll examine how to implement this file attachment capability in web forms, ensuring a user-friendly experience for submitting digital content.
Odoo offers a predefined model called 'ir.attachment' for managing uploaded files. With this model, end users can submit and store attachments directly through web forms. In this blog, we’ll explore how to make use of this functionality in a practical example.
attachment_ids = fields.Many2many('ir.attachment', string='Attachments')
First, we need to add a field in the required model for storing the attachments in 'ir.attachment', as shown in the above example.
To add the field in the web form, we need to create an XML file. In this file, we begin by using the 'form' tag to define all the necessary fields, including one for uploading files. The 'form' tag also supports attributes like 'class', 'action', 'method', and 'enctype', which help control how the form looks and works. Importantly, the 'enctype' attribute is essential when handling file uploads. It tells the browser not to alter or encode the file content. Below is an example of a 'form' tag that uses this attribute.
<form action="/form/submit" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token"
t-att-value="request.csrf_token()"/>
<div class="form-group col-md-6">
<label for="att">Attach file</label>
<input type="file" name="att" class="form-control"
accept="image/,application/pdf,video/"/>
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary">submit
</button>
</div>
</form>
And this will create a field, as shown in the image below.

The CSRF tokens are important for securing forms against Cross-Site Request Forgery attacks. In the form, file attachments are handled using 'label' and 'input' elements, offering a simple upload interface. The 'name' attribute ('att') is used to identify the uploaded content, while the 'accept' attribute restricts uploads to images, PDFs, and videos. A 'button' element is included to submit the form and begin the data-saving process.
In the controller, a corresponding function should be created to handle the encoding of the uploaded file and store it in the database. The following is an example of how this function can be implemented in Odoo 18:
@http.route(['/form/submit'], type='http', auth='public', website=True)
def file_upload(self, redirect=None, **kw):
current_partner = request.env.user.partner_id
uploaded_file = kw.get('att')
if uploaded_file:
file_name = uploaded_file.filename
file_content = uploaded_file.read()
attachment = request.env['ir.attachment'].sudo().create({
'name': file_name,
'type': 'binary',
'datas': base64.b64encode(file_content),
'res_model': 'res.partner',
'res_id': current_partner.id,
})
current_partner.sudo().write({
'attachment_ids': [(4, attachment.id)],
})
return request.redirect(redirect or '/')
By following this approach, you can allow users to upload files directly through a web form in Odoo 18 and store those files as attachments linked to specific records. This makes it easier to manage uploaded content and keep everything organized within the system.
To read more about How to Create a Custom Web Form View in Odoo 18, refer to our blog How to Create a Custom Web Form View in Odoo 18.