Skip to main content
iVentureTeam

percentpie

The little circles on a mailing's statistics, Opened 54%, Clicked 12%, are percentpie: a display-only widget that draws a number as a filled circle using nothing but a CSS conic-gradient.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 19, 2026Updated August 19, 20266 min read
Odoo 19 mass mailing form showing percentpie circles for the Opened, Replied, Clicked, Received and Bounced ratios.
Studio namePercentage Pie
Technical namepercentpie
Field typesfloat, integer
Viewsform, kanban (dashboard blocks)
Moduleweb, present in every Odoo database
Used in core5 occurrences across 1 module: the mailing statistics ratios in mass_mailing
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupYes: pick the Percentage Pie widget on an Integer or Decimal field in Studio
Alternativesprogressbar, percentage, gauge

What the PercentPie field does

Some numbers read better as shapes. Open a sent mailing in Odoo's Email Marketing and the statistics row shows five circles, each partially filled: opened, replied, clicked, received, bounced. Each circle is one percentpie widget over one computed ratio field.

The implementation is satisfyingly small. The template renders a <figure> whose background is a CSS conic-gradient: the active color sweeps from 0 percent to the field's value, the static color fills the rest. The number itself is printed in the middle, formatted to at most two decimals with trailing zeros trimmed, plus a percent sign, and the field's label (or the string attribute) sits underneath. No SVG, no canvas, no JavaScript charting, which is why it costs nothing to render even when a kanban shows fifty of them.

It is display-only in the strictest sense: there is no editing path, no click behavior, and no options to configure. The only thing you can change from the view is the label.

What this means for your team

percentpie is the fastest way to make a KPI legible on a form or dashboard-style kanban.

The mailing statistics row is the model to copy: five ratios a marketer needs to compare at a glance, and comparing five filled circles is faster than reading five numbers. The same works for on-time delivery rate per carrier, occupancy per room type, scrap rate per work center, margin percentage per project card, any percentage a manager scans across many records.

The design constraint is honesty about the scale. The circle maps 0 to 100 literally: a fill that looks like a quarter circle IS 25 percent. That means your compute must deliver values on the 0 to 100 scale (see the trap below), and values that can exceed 100 belong in a progressbar with an overflow style rather than a pie that clips confusingly at full.

Setting it up in Odoo Studio (no code)

Studio ships this widget under a friendlier name.

  1. Open the form or kanban in Studio.

  2. Add an Integer or Decimal field, or select an existing one, typically a computed ratio.

  3. In the Properties tab, set Widget to Percentage Pie.

  4. Set the Label; it becomes the caption under the circle.

What Studio cannot do here

Studio covers everything this widget can do, because there is nothing to configure: no options exist. What Studio cannot fix either is the scale: if the underlying field stores a fraction (0.54), the circle will render 0.54 percent. The scaling belongs in the computed field's Python, not in the view.

Working examples

As Email Marketing uses it

<field name="opened_ratio" string="Opened" widget="percentpie"/>

A KPI on your own model

on_time_rate = fields.Float(compute="_compute_on_time_rate")

def _compute_on_time_rate(self):
    for rec in self:
        total = len(rec.delivery_ids)
        # scale to 0-100: the widget does NOT multiply for you
        rec.on_time_rate = total and 100.0 * len(rec.delivery_ids.filtered("is_on_time")) / total
<field name="on_time_rate" string="On time" widget="percentpie"/>

Recoloring the gauge

.o_field_percent_pie {
    --PercentPieField-color-active: #28a745;
    --PercentPieField-color-static: #e9ecef;
}

One conic-gradient, three quirks

The template is worth reading because it explains every quirk in one glance:

background: conic-gradient(
    var(--PercentPieField-color-active) 0% {{value}}%,
    var(--PercentPieField-color-static) 0% 100%
)

The raw value goes straight into CSS. No clamping, no scaling. A value of 250 renders a fully filled circle (the gradient saturates), a negative value renders empty, and a fraction renders as a sliver. The printed number, however, shows the actual value, so a mis-scaled compute is immediately visible as a full-looking circle labeled 0.54%.

The printed number and the fill can disagree in precision. The fill uses the raw value; the label formats with formatFloat at up to 2 decimals, trailing zeros trimmed (54 renders as 54, not 54.00), which is also why an integer field works just as well as a float.

There is no aggregation magic. Unlike project_task_progressbar, percentpie registers nothing in the formatters registry, so list-view sums and pivot measures of the same field are formatted as plain numbers.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Behavior unchanged on the development branch; internal props-schema rework only.
Odoo 19.0VerifiedVerified against the shipped source.
Odoo 18.0VerifiedByte-identical to 19.0.
Odoo 17.0VerifiedIdentical apart from the module pragma line.
Odoo 16.0VerifiedPresent with the same rendering.

Upgrade note. Nothing to migrate: the widget's behavior is identical from Odoo 16 through 19, and views carry over untouched. Only deep CSS overrides written before the CSS-variable colors should be rechecked.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The notes below are read from the public development branch and are not final until release.

No behavioral changes: on master the component migrates to the new props-schema API (useProps and a shared percentPieFieldProps export), with the template, the conic-gradient and the empty options list unchanged. Only JavaScript that spreads this component's props is affected. We re-verify against the shipped release.

Common problems and fixes

SymptomCause and fix
The circle is nearly empty but the ratio should be 54%The field stores a fraction (0.54); the widget maps the raw value onto 0 to 100 without scaling. Multiply by 100 in the compute method. The printed number doubling as 0.54% is the giveaway.
The circle is always completely fullThe value exceeds 100 (for example a count instead of a ratio); the CSS gradient saturates at full. Fix the compute to produce a 0 to 100 ratio, or use progressbar with a max value for open-ended numbers.
Users ask to edit the value in the circleThe widget is display-only; there is no input element at all. Percentages like these should be computed. If manual entry is really needed, use the percentage widget instead.
You need different colors for good and bad valuesThe two colors are fixed CSS variables; there is no option or decoration support on the widget. Override --PercentPieField-color-active in SCSS, scoped to a class you set on the field, one scope per color rule.
The label under the circle shows the technical field nameNo string attribute on the field element and no model-level label. Set string="..." on the field; it is the only prop the widget reads from the view.

PercentPie field vs the alternatives

WidgetBest forKey difference
percentpieA bounded 0 to 100 KPI scanned at a glancePure CSS circular gauge; zero options, always read-only
progressbarProgress toward a target that can be exceededHorizontal bar with max value, overflow styling and optional editing
percentageAn editable percentage in a form or listPlain formatted number with a % sign; stores fractions, unlike percentpie
gaugeDashboard-style dial with a target on kanban cardsA richer graphical gauge, kanban-oriented

Pick by geometry and range: a pie for a bounded 0 to 100 snapshot, a progressbar when there is a target that can be exceeded, plain percentage when the number should be editable or space is tight.

Frequently asked questions

Why does my percentpie show almost 0% when the value is 0.54?+
The widget expects values already on the 0 to 100 scale and does no multiplication. Store 54, not 0.54, in the computed field. This is the opposite convention from the percentage widget, which works with fractions.
Can users edit the value inside the pie?+
No. The widget renders a figure and two spans; there is no input. It is meant for computed ratios, so editability would not make sense.
How do I change the pie's colors?+
Through CSS variables: override --PercentPieField-color-active and --PercentPieField-color-static on .o_field_percent_pie in your theme or module SCSS. There are no color options in the widget.
Is percentpie heavy to render on kanban cards?+
No. The pie is a single CSS conic-gradient on a figure element, with no chart library or canvas involved, so dozens per screen are effectively free.
Where does Odoo itself use percentpie?+
On the mailing statistics of Email Marketing: the Opened, Replied, Clicked, Received and Bounced ratio circles are all this widget over computed float ratios.
How do I add a Percentage Pie in Studio?+
Add or select an Integer or Decimal field and set its Widget property to Percentage Pie. Remember the stored value must be on the 0 to 100 scale; Studio cannot rescale it for you.

KPIs your managers can read across the room?

The right widget over the right computed field turns a form into a dashboard, no BI tool needed. We build the ratio fields, pick the gauges, and wire Odoo screens that surface on-time rates, margins and conversion at a glance.

Build our KPI views

How this page was produced

This page was verified by reading percent_pie_field.js and its template on the Odoo 19.0 branch, including the formatFloat call with trailingZeros false and the conic-gradient that consumes the raw value. Version stability was confirmed by diffing the file against 16.0, 17.0, 18.0 and the development branch; the mailing statistics usage is quoted from the shipped mass_mailing views. Spotted an error or a version difference? Tell us and we will correct the page.