Introduction
When you look at a product description in an Odoo e-commerce shop, the formatted text with bold headings, bullet points, and images is powered by a single field type: the Html field. It is one of the most versatile fields in the Odoo data model, and it shows up in more places than most users realize.
Unlike a plain text field that stores simple strings, the Html field stores rich content with full formatting. This makes it essential anywhere users need to write structured or styled text, whether that is a product description, an email template, an internal note, or a website section.
This guide covers what the Html field is, how it works in the Odoo ORM and database, where it is used across real business workflows, and how to create or customize it using Odoo Studio or Python code. We also cover the most common mistakes people make when working with this field type.
What is the Html Field in Odoo
In the Odoo ORM, the Html field is designed to store formatted HTML content. It maps to a TEXT column in PostgreSQL, and the stored value is an HTML string. Odoo handles the rendering and sanitization automatically, so what users see in the interface is a fully formatted rich text editor, not raw HTML code.
From the user perspective, an Html field appears as a WYSIWYG editor (What You See Is What You Get). Users can apply bold, italic, headings, lists, links, tables, and even insert images directly in the field. The result is saved as structured HTML behind the scenes.
Here is how the field looks in a Python model definition:
from odoo import fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
x_technical_specs = fields.Html(
string='Technical Specifications',
sanitize=True,
sanitize_tags=True,
)
The string parameter sets the visible label. The sanitize parameter controls whether Odoo strips potentially dangerous HTML before saving the value. This is important for security reasons and is enabled by default.
In Odoo Studio, this field type is called Html or Rich Text. When created through Studio, it gets an x_studio_ prefix. When defined in Python or via the XML-RPC API, you choose the technical name yourself.
How the Field Works
When you define an Html field in Odoo, the framework creates a TEXT column in the PostgreSQL database. There is no length constraint at the database level, which makes it suitable for long-form content. The Odoo framework manages the sanitization layer before the value is written to the database.
Sanitization and Security
The most distinctive behavior of the Html field compared to other field types is its sanitization layer. By default, Odoo strips any HTML tags or attributes that could be used for cross-site scripting (XSS) attacks. This is controlled by a set of field attributes:
- sanitize: When
True(the default), Odoo applies the full sanitization process before saving the value. Set toFalseonly when you are certain the content comes from a trusted source and must preserve raw HTML. - sanitize_tags: When
True, Odoo removes any HTML tags not on the allowed list. Disabling this allows arbitrary tags but should be done with caution. - sanitize_attributes: Controls whether attributes on HTML tags are also sanitized.
- sanitize_style: Controls whether inline style attributes are sanitized. By default, certain CSS properties are allowed while potentially dangerous ones are stripped.
- strip_style: When
True, removes all inline style attributes entirely. - strip_classes: When
True, removes all CSS class attributes from the stored content.
This sanitization makes the Html field safe to use for user-generated content, which is why it appears on customer-facing forms and email templates throughout Odoo.
Key Field Attributes
Beyond sanitization, the Html field shares many of the standard Odoo field attributes:
- translate: When set to
True, the field content can be translated per language. Odoo stores a separate version of the HTML for each active language in the database. - required: Makes the field mandatory. Note that an Html field containing only whitespace or empty tags will still appear non-empty to the interface, so required validation works best on truly blank values.
- default: Sets a default HTML value for new records. Useful for pre-populating email templates or product descriptions with standard boilerplate.
- compute: Links a Python method that builds the HTML content dynamically. With
store=True, the result is persisted in the database. - copy: Controls whether the HTML content is duplicated when copying a record. Defaults to
True.
How It Appears in Views
In form views, an Html field renders as the Odoo rich text editor. Users get a toolbar with formatting options and the content area handles styled text, images, and links. In list views, Odoo typically displays a plain text preview with HTML tags stripped, to keep the list readable.
The widget attribute in XML views lets you control the rendering. The default widget for Html fields is the rich text editor. You can also render an Html field as read-only HTML output using the html widget, which is useful in report views or on portal pages where you want to display formatted content without an editable toolbar.
Interaction with the Odoo ORM
From a development standpoint, reading an Html field returns a string containing the raw HTML markup. Writing to it expects an HTML string as well. The sanitization happens at the ORM level before the write reaches the database, so even values written via the XML-RPC API go through the same cleaning process when sanitize=True.
One practical implication: if you need to store and retrieve content that includes custom HTML tags or attributes not on Odoo's allowed list, you will need to set sanitize=False or adjust the sanitize flags on the field definition. This is an advanced use case that requires careful consideration of the security implications in your deployment.
Business Use Cases
The Html field appears in many areas of an Odoo implementation. Here are five real-world examples from common business workflows.
Inventory and E-commerce: Product Descriptions
The most widely used Html field in Odoo is the description_sale field on product.template. This is the product description that customers see on the website shop and in sale order lines. Using an Html field here lets merchandising teams write structured product content with bullet points, headings, and embedded images, all of which translates directly into better e-commerce conversions. The same product record powers both the back-office and the storefront, so there is no duplication of content between systems.
Email Marketing: Template Bodies
Odoo's email templates rely heavily on Html fields. The body_html field on mail.template stores the entire email body as HTML, including layout, images, and dynamic placeholders that get replaced with real values at send time. Marketing teams can design rich email content directly in Odoo without needing an external email design tool. The content is versioned and reusable across campaigns, quotations, and automated workflows.
CRM: Notes and Opportunity Descriptions
Sales teams often need to capture detailed context about a prospect or deal. Html fields on CRM leads and opportunities allow reps to write structured notes with formatting, lists, and embedded links to external documents or proposals. This is more useful than plain text fields when notes need to be shared across a team or included in printed reports, since the formatting survives across all these contexts.
Accounting: Invoice Terms and Conditions
Many companies include payment terms, legal clauses, or warranty information at the bottom of invoices and sale orders. The note field on sale orders and invoices is an Html field, allowing finance and operations teams to format these terms with proper structure. The content appears cleanly on printed PDF documents, with line breaks and emphasis preserved exactly as entered.
HR: Job Position Descriptions
When HR teams post job openings through Odoo Recruitment, the job description is stored in an Html field on the hr.job and hr.applicant models. This allows structured job postings with clear sections for responsibilities, requirements, and benefits, exactly the kind of formatted content that looks professional on a careers page and helps attract the right candidates.
Creating or Customizing the Html Field
There are three main ways to add an Html field to an Odoo model, depending on your technical setup and deployment approach.
Using Odoo Studio (No Code)
Odoo Studio makes it straightforward to add an Html field to any existing form without writing code:
- Open Odoo Studio from the main menu.
- Navigate to the form where you want the field.
- From the sidebar, drag an Html or Rich Text field onto the form.
- Set the label and any other options in the field properties panel.
- Save and close Studio.
Studio automatically creates the field with an x_studio_ prefix, adds it to the view, and handles the database column. No migration or deployment step is needed on your side. The field is immediately available for data entry across the instance.
Using Python in a Custom Module
For developers building Odoo modules, Html fields are defined in Python model files. This approach is recommended for any customization that needs to be version-controlled and deployed across staging and production environments:
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
x_delivery_instructions = fields.Html(
string='Delivery Instructions',
sanitize=True,
translate=True,
)
After defining the field in the model, add it to the relevant view XML file so it appears in the interface. Odoo handles the TEXT column creation in the database automatically when you install or upgrade the module. The field will render as a rich text editor in the form view without any additional widget configuration.
Using the XML-RPC API
If you manage Odoo customizations programmatically as part of a deployment pipeline or a remote configuration script, you can create Html fields via the XML-RPC API:
field_id = models.execute_kw(
ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_custom_notes',
'field_description': 'Custom Notes',
'model_id': model_id,
'ttype': 'html',
'state': 'manual',
}]
)
The ttype: html value tells Odoo to create an Html field. The state: manual setting marks it as a user-created field rather than one defined by a module. This is the same approach Dasolo uses for remote field creation in client environments, as part of automated configuration notebooks that can be run and tracked without direct server access.
Note that sanitization options (sanitize, sanitize_tags, etc.) are not settable via the API on ir.model.fields in the same way they are in Python. The default sanitization behavior applies when creating fields through the API.
Best Practices
1. Keep sanitize enabled unless you have a strong reason not to
The default sanitization behavior exists to protect your Odoo instance from cross-site scripting vulnerabilities. Most use cases work perfectly with sanitization on. Only disable it when you are storing content generated by a fully trusted internal process, such as a server-side rendering pipeline, and never when the content comes from user input or external sources.
2. Use translate=True for multilingual product content
If your Odoo instance supports multiple languages, Html fields displayed on the website or on customer-facing documents should have translate=True. This allows your team to maintain separate HTML content for each language, ensuring that customers always see descriptions and terms in their own language rather than a fallback.
3. Avoid storing Html field content that relies on external resources
Embedding external images or scripts inside an Html field creates dependencies that can break silently when those external URLs change or go offline. Use Odoo's attachment system to host images internally, and reference them with relative URLs. This keeps your content portable and resilient across database migrations and server changes.
4. Use computed Html fields for dynamic document content
For content that needs to be built programmatically, such as a formatted summary of order lines or a dynamic warranty clause, a computed Html field with store=True is a clean solution. The computation logic lives in one place, the output is stored in the database for fast access, and the field renders properly in both the interface and in PDF reports.
5. Consider the rendering context when choosing Html vs Text
If the content will only ever appear in the Odoo backend in a context where users read it as plain text, a Text field may be sufficient. Use Html when the formatting actually matters for the reader, such as on a website page, a printed document, or an email. Adding an Html field where a plain Text field would do introduces unnecessary complexity for users who have to interact with a rich text editor for simple note-taking.
Common Pitfalls
Disabling sanitize and forgetting about it
Setting sanitize=False on a field that users can edit directly is a security risk. It is easy to do this during development to unblock a formatting requirement, and then forget to revisit it before going to production. Always document why sanitization is disabled and plan a review before deployment.
Pasting content from external sources with broken HTML
When users paste content from Word documents, Google Docs, or websites into an Html field, the result often contains messy or non-standard HTML. This can lead to inconsistent rendering, invisible characters that break searches, or bloated field values that slow down page loads. Encourage users to use the "Paste as plain text" option first and then reapply formatting inside the Odoo editor.
Confusing Html field with the website builder content
Odoo's website builder uses building blocks and Owl components to construct page content. The HTML stored by the website builder in page views is not the same as what you would put into a standard Html field. Trying to copy complex website builder HTML into an Html field on a model will usually not render correctly and may be stripped by the sanitizer.
Forgetting translate on multilingual deployments
In a multilingual Odoo instance, an Html field without translate=True shows the same content to users of all languages. This is fine for internal fields, but becomes a problem for product descriptions, email templates, and any content that reaches external contacts. Missing this setting is easy to overlook during initial setup and difficult to fix retroactively once content has been entered in only one language.
Using Html fields in places where plain text is expected
Some parts of Odoo, such as email subjects, report titles, or external API responses, expect plain text strings. If you store an Html field value in a context where the HTML tags are not stripped, your users will see raw markup like <p>Hello</p> instead of clean text. Always check how and where the field value will be consumed before choosing Html over Char or Text.
Conclusion
The Html field is one of the most powerful field types in the Odoo data model. It sits quietly behind product descriptions, email templates, job postings, and invoice notes, making formatted content possible throughout the system without any additional tooling.
Understanding how it works, particularly the sanitization layer, the translation support, and how it behaves across different rendering contexts, helps you make better decisions when designing or customizing an Odoo instance. Whether you are using Odoo Studio to add a rich text field to a form, defining it in Python as part of a custom module, or creating it remotely via the API, the principles covered in this guide apply across all three approaches.
Like most things in Odoo, the field itself is straightforward once you know what it is doing under the hood. The value comes from using it in the right places, with the right settings, for the right type of content.
At Dasolo, we help companies implement, customize, and optimize Odoo across all departments. Whether you need help designing a clean data model, adding custom fields to your workflows, or building complete Odoo modules tailored to your business, our team is here. Reach out to us and let's talk about your Odoo project.