How to Implement _origin in Odoo?
✅ What is _origin?
In Odoo, every recordset has a special attribute called _origin, which refers to the original database record that a given record was derived from — before any changes or duplication.
This attribute is especially useful when dealing with new/virtual/in-memory records (e.g., created using copy(), new(), or in transient models).
🔍 Use Case
_origin is often used internally by Odoo to:
- Detect whether a record is newly created or duplicated.
- Compare with the original record.
- Track original references during onchange, copy, or create flows.
✅ Realistic Odoo Example
🧾 Use Case: Copying a Sale Order and Reusing Certain Fields from the Original
class SaleOrder(models.Model):
_inherit = 'sale.order'
def copy(self, default=None):
res = super().copy(default)
if self._origin:
_logger.info(f"Copied from: {self._origin.name}")
# Use something from the original
res.note = f"Copied from order: {self._origin.name}"
return res
🔁 What's Happening:
- self is the temporary, new copy (not yet committed).
- self._origin is the original sale order being copied.
- You can access fields from _origin to carry over notes, references, or custom values.
- _origin is only relevant in virtual/in-memory contexts.
- For regular, saved records: record == record._origin
- record._origin.id gives you the original database ID.
🧠 Where _origin is Used
Scenario | Purpose of _origin |
record.copy() | Reference to the original source record |
record.new(data) | Keeps track of the original DB record |
Transient models (wizards) | Often used to compare input vs original |
Onchange methods | Compare user input with source values |
❗️ Important Notes
✅ Summary
Attribute | _origin |
Used In | Virtual/unsaved/temporary recordsets |
Points To | Original database record |
Use Case | Compare values, fetch original refs |
Common In | copy(), new(), transient models |