Skip to main content
iVentureTeam

x2_many_media_viewer

The Add Media gallery on eCommerce products is a one2many wearing a media manager. x2_many_media_viewer swaps the usual Add row for Odoo's image and video dialog, and can transcode every upload to WebP.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 25, 2026Updated August 25, 20266 min read
Odoo 19 product form Extra Media gallery rendered by the x2_many_media_viewer widget with the Add Media button and image cards.
Technical namex2_many_media_viewer
Field typesone2many, many2many
Viewsform (kanban sub-view)
Modulehtml_editor, auto-installed with the editor
Used in core2 occurrences in website_sale: template and variant Extra Media galleries
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupNo. Applied in view XML on a one2many of image records
Alternativesone2many, many2many_binary, image

What the media viewer field does

The Extra Media block on a product template is technically just a one2many to product.image shown as an embedded kanban. What makes it feel like a gallery manager is this widget. x2_many_media_viewer extends the standard x2many field and overrides exactly one interaction: the Add button no longer creates an empty row, it opens the html editor's media dialog with the Images and Videos tabs and multi-select enabled.

From there the widget translates dialog picks into records. A video pick becomes a new line whose name is platform - [Video] and whose video_url receives the normalized player URL. An image pick is looked up in ir.attachment, its base64 payload read, and a new line is created with the data written into every field of the sub-view that matches the hardcoded list image_1920, image_1024, image_512, image_256, image_128, plus the file name.

The template also moves the kanban renderer above the control panel, which is why the gallery reads pictures first, buttons second, unlike every other x2many.

What this means for your team

Product pages sell with media, and this widget is what makes maintaining that media tolerable at catalog scale. Merchandisers pick a dozen shots in one dialog pass instead of creating rows one by one, videos drop in by pasting a YouTube or Vimeo link, and the same flow covers per-variant galleries, the red one shows red photos.

The convert_to_webp option is the quiet page-speed lever: every upload is transcoded to WebP with resized renditions, typically cutting image weight substantially versus JPEG at similar quality, with JPEG twins retained for consumers that cannot read WebP, like PDF reports. Core switches it on for both eCommerce galleries, so a stock Odoo shop gets modern formats without anyone thinking about it. If your storefront's Lighthouse score complains about image formats, checking that your custom galleries pass this option is the two-minute fix.

Supported options in Odoo 19

The descriptor spreads the base x2many descriptor, so the declared options are the standard x2many crud set (create, delete, link, unlink...). The widget's own knob below is read in extractProps only, which makes it invisible to any option panel. Verified in Odoo 19.0 source.

OptionTypeWhat it does
convert_to_webpboolean (undocumented)Transcodes every picked image (except GIF and SVG) to WebP and generates resized WebP plus JPEG attachments at 1024, 512, 256 and 128. Read only in extractProps; absent from the declared option list. Core enables it on both eCommerce galleries.(since Odoo 18.0)
create / delete / link / unlinkboolean or domain (inherited)The standard x2many crud gates are inherited unchanged from the base descriptor and still control the embedded kanban's abilities.

The target model's field names are a contract. Videos require a video_url char field and images require the image_1920 family in the sub-view; records land with whatever subset exists there. Core's product.image model is shaped exactly for this. Point the widget at a one2many of anything else and picks either drop data or create half-empty lines.

Working examples

The core usage, from the product form

<field name="product_template_image_ids" mode="kanban"
       add-label="Add Media" nolabel="1"
       widget="x2_many_media_viewer"
       options="{'convert_to_webp': True}"/>

The variant form repeats the same element on product_variant_image_ids. add-label renames the dialog trigger, and the WebP option is on in both core usages.

A custom gallery model

# fields your model needs for full behavior
name = fields.Char()
video_url = fields.Char()
image_1920 = fields.Image(max_width=1920, max_height=1920)

Mirror product.image's shape, then use the widget on the one2many exactly like core does.

Inside the WebP pipeline and the URL-attachment trap

The WebP pipeline is copied, per the source's own comment, from the image field's upload handler, and it is worth knowing what it actually creates. For each picked image that is neither GIF nor SVG, the browser draws it on a canvas at the original size and again at 1024, 512, 256 and 128 where smaller than the original. Each size is exported twice, once as WebP and once as JPEG, and stored via ir.attachment.create_unique as attachments chained to the first WebP; the JPEG twins exist because PDF reports cannot embed WebP. The record's image fields then receive the full-size WebP data. One behavioral footnote: Odoo 18 exported WebP at an explicit 0.75 quality, 19 calls the browser default instead, so the same upload can weigh slightly differently across versions.

The other sharp edge is attachment provenance. The dialog can hand back URL-type attachments, common with demo data, which have no binary payload. The widget detects the missing data and refuses the pick with a warning naming the attachment, and the source carries a TODO admitting URL attachments are simply unsupported. Re-uploading the file turns it into a binary attachment and unblocks the pick. Note also that the rejection happens mid-loop, so in a multi-pick the files before the URL attachment are added and the rest are abandoned.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. New options, auto-loaded fields and video thumbnails on the development branch. See below.
Odoo 19.0VerifiedFile moved into html_editor's fields folder; WebP export uses default quality.
Odoo 18.0VerifiedIntroduced with html_editor; WebP exported at quality 0.75.
Odoo 17.0Not availableWidget does not exist; galleries were plain x2many kanbans.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. Moving from 18 to 19 requires no XML changes; the file moved inside html_editor and the media dialog API swapped its tab flags, both invisible to views. Custom patches on the 18 file path need their import updated.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. We read the widget on the public development branch at the time of writing; the branch is unstable and can change before release.

The development branch grows the widget considerably: three new undocumented options appear next to convert_to_webp, force_create, set_attachment_id and only_image, the last hiding the Videos tab; the widget starts declaring relatedFields so name, image_1920 and video_url (or attachment_id in attachment mode) are auto-loaded instead of relying on the sub-view; video picks now also fetch the platform thumbnail and store it as the record's image; and the whole resize pipeline moves to a shared saveMultipleAttachments helper in web core. We re-verify after release.

Common problems and fixes

SymptomCause and fix
Cannot add URL type attachment warningThe picked attachment stores a URL, not binary data; the widget only consumes binary attachments. Re-upload the image file so a binary attachment exists, then pick again.
Video pick creates a line but the site shows nothingThe target model lacks a video_url field, or the URL platform was not recognized. Mirror product.image's video_url field and paste a standard YouTube or Vimeo link.
Images upload but stay JPEG or PNGconvert_to_webp is not passed in the view's options; the widget does not default it on. Add options="{'convert_to_webp': True}" like the core product views.
GIF or SVG did not convert to WebPBoth formats are deliberately excluded from the pipeline to preserve animation and vectors. Expected behavior; convert externally if you need stills.
Multi-pick added only some of the imagesThe loop stops at the first URL-type attachment it hits, abandoning the rest of the batch. Fix or drop the offending attachment and re-pick the remainder.
Gallery renders below the buttons instead of aboveA custom template override lost the widget's renderer relocation. Keep the html_editor.X2ManyMediaViewer template inheritance intact.

Media viewer field vs the alternatives

WidgetBest forKey difference
x2_many_media_viewerGallery one2manys where picks come from the media dialog: product images and videosReplaces the x2many Add flow with the media dialog and an optional WebP transcode pipeline
one2manyOrdinary embedded lists and kanbans of child recordsAdd creates an empty row or opens a form dialog; no media dialog, no transcoding
many2many_binaryAttaching multiple files to a record without a gallery modelWrites ir.attachment links directly; no image fields, no video URLs
imageOne image stored on the record itselfSingle binary field with its own upload and WebP option, no collection semantics

Reach for this widget when picks should become records in a gallery model. When files should simply hang off the record, the attachment widgets below are the right tool, and a single image field stays a plain image.

Frequently asked questions

Which video platforms work in the Videos tab?+
The dialog recognizes the platforms Odoo's video helper knows, YouTube, Vimeo, Dailymotion, Youku, and normalizes the pasted link into a player URL stored in video_url. Unrecognized links do not produce a pick.
Why does every image create several attachments?+
That is the convert_to_webp pipeline: for each size that is smaller than the original (1024, 512, 256, 128) it stores a WebP and a JPEG twin, chained to the main WebP attachment. Reports use the JPEG twins because PDF generation cannot embed WebP.
Can I use the widget on my own model?+
Yes, if the child model looks like product.image: a name char, an image_1920 image field (the smaller renditions help) and a video_url char if you want the Videos tab to be useful.
Does the widget resize the images it stores on the record?+
The record's own field receives the full-size payload (WebP if conversion is on); the smaller renditions exist as attachments and through Odoo's standard image field resizing. Display size on the website is handled by the storefront, not the widget.
Is x2_many_media_viewer available in Odoo 17?+
No. It ships with the new html editor in Odoo 18. On 17 and earlier, product media blocks are plain x2many kanbans where you add rows and upload into each.

Product pages heavy, galleries painful to maintain?

Media pipelines decide storefront speed. We tune Odoo eCommerce catalogs end to end, WebP galleries, variant media, CDN and Core Web Vitals, so your product pages load fast and your team stops fighting the back office.

Book a free consultation

How this page was produced

Verified by reading x2many_media_viewer.js and its template in the Odoo 19.0 html_editor module, the base x2many descriptor it spreads, and both core usages in website_sale product views. The 18.0 original was diffed for the quality and dialog-flag changes, and the Odoo 20 section reflects the development branch rework. Spotted an error? Tell us and we will correct the page.