Introdução
Se já abriu uma encomenda de venda no Odoo e viu uma tabela de linhas logo abaixo dos dados do cliente, já teve contacto com um One2many. Este tipo de campo é um pilar do modelo de dados do Odoo: serve para representar listas de itens dependentes de um registo “pai”, e é fundamental para quem desenvolve ou configura o sistema.
Este guia mostra, de forma prática, o que é um One2many, como o Odoo o implementa internamente, quando faz sentido usá-lo na sua solução e de que maneiras o pode criar — quer usando Odoo Studio, quer codificando em Python.
Seja você um utilizador que quer compreender a organização dos seus dados, seja um programador à procura de instruções claras, encontrará aqui os conceitos essenciais e exemplos aplicáveis no dia a dia.
O que é o campo One2many no Odoo
No Odoo, One2many é um tipo de campo relacional que liga um registo pai a vários registos filhos pertencentes a outro modelo.
Pense nisto como um contrato que reúne várias tarefas: um único registo principal pode “conter” uma lista de registos associados. Exemplos práticos: um cliente com várias faturas, uma encomenda com várias linhas, ou um projeto com várias tarefas associadas ao mesmo projeto mãe.
Na interface, o One2many aparece normalmente como uma lista embutida dentro do formulário do registo pai. Esta tabela inline permite adicionar, editar ou remover registos filhos sem sair do formulário principal, tornando a gestão de dados mais fluída para o utilizador.
Diferenças face a outros campos relacionais
O Odoo disponibiliza sobretudo três tipos de relações no seu ORM:
- Many2one: um registo que aponta para um único registo noutro modelo (por exemplo, uma encomenda para um único cliente).
- One2many: um registo que agrega vários registos de outro modelo (por exemplo, uma encomenda com várias linhas).
- Many2many: ligação muitos-para-muitos, onde registos de ambos os lados podem estar relacionados entre si (por exemplo, produtos ligados a várias etiquetas e vice-versa).
Usa-se One2many quando cada registo filho pertence a um único pai. Se for necessário partilhar o mesmo registo filho entre vários pais, a escolha adequada é Many2many.
Uma particularidade do One2many é que ele não guarda dados na tabela do pai: trata-se de um campo virtual que mostra registos a partir do modelo filho, baseado num Many2one existente nesse modelo filho.
Como funciona este campo
Na base de dados, não há colunas adicionais na tabela do registo pai para armazenar um One2many. A ligação efetiva é feita por uma chave estrangeira na tabela do filho que aponta para o ID do pai.
É um princípio central do ORM do Odoo: cada One2many tem por trás um Many2one no modelo relacionado. O One2many funciona como uma pesquisa inversa — o Odoo encontra todos os filhos cujo campo Many2one corresponde ao ID do pai atual.
Relação entre One2many e Many2one
Ao definir um One2many em Python, há dois parâmetros chave a indicar:
- comodel_name: o nome do modelo que contém os registos filhos.
- inverse_name: o nome do campo Many2one no modelo filho que referencia o pai.
Um exemplo simples num módulo personalizado mostra como um contrato pode ligar-se a vários entregáveis:
deliverable_ids = fields.One2many(
comodel_name='service.deliverable',
inverse_name='contract_id',
string='Deliverables'
)
Neste caso, contract_id é o campo Many2one definido no modelo service.deliverable que aponta para o contrato. Sem esse Many2one, o One2many não tem base para operar.
O que acontece na base de dados
Os dados realmente residem na tabela do modelo filho: cada linha do filho inclui uma coluna de chave estrangeira que guarda o ID do pai a que pertence.
Quando o Odoo precisa mostrar o One2many de um registo pai, executa internamente uma consulta que procura todas as linhas do filho cuja chave estrangeira corresponde ao ID do pai — comportamento típico de bases relacionais, gerido automaticamente pelo ORM do Odoo.
Por isso o One2many é tratado como um campo do tipo ‘view’ no Python do Odoo que não adiciona colunas à tabela física do pai; é uma visão computada das relações existentes.
Casos práticos de utilização nas empresas
Os One2many estão presentes por todo o Odoo porque mapeiam naturalmente relações pai-filho do mundo real. A seguir, alguns exemplos práticos retirados de cenários comuns nas empresas.
1. Encomendas de venda e linhas de encomenda
No módulo de Vendas, o modelo das encomendas usa um One2many (por exemplo order_line_ids) para listar as linhas de encomenda. Cada linha contém produto, quantidade, preço unitário e desconto. Os utilizadores podem gerir estas linhas diretamente no formulário da encomenda.
2. Faturas e linhas de fatura
Na contabilidade, a fatura agrega linhas de item através de um One2many (por exemplo invoice_line_ids), onde cada linha representa um produto ou serviço faturado e o total da fatura resulta da soma desses itens.
3. Projetos e tarefas
No módulo de Projetos, o projeto contém um One2many para listar todas as tarefas associadas. Na interface isso pode ser mostrado como lista, kanban ou Gantt, consoante a vista escolhida, tudo sustentado pela mesma relação One2many.
4. Contactos e contactos secundários
O modelo res.partner usa child_ids como One2many para listar contactos ligados a uma empresa. Cada contacto tem um Many2one (parent_id) que aponta para a empresa mãe.
5. Modelos personalizados em serviços ou produção
Ao criar módulos personalizados, sempre que um registo “agrupa” vários sub-registos (ex.: uma ordem de manutenção com várias peças, um curso com várias sessões, ou um contrato com vários entregáveis), o One2many é a escolha natural.
Essa versatilidade explica por que motivo o One2many é tão central na personalização do Odoo e na modelação de processos específicos de cada setor.
Como criar ou personalizar o campo
Existem duas formas principais de adicionar um One2many: pelo Odoo Studio (sem código) ou diretamente por código Python num módulo personalizado.
Criar com Odoo Studio
No Studio não consegue criar um One2many diretamente no modelo pai sem antes ter o Many2one no filho. O One2many depende da existência prévia do campo inverso no modelo filho.
O fluxo recomendado em Studio é simples:
- Abra o modelo filho no Studio e adicione um campo Many2one que aponte para o modelo pai.
- Depois de guardar esse campo no filho, volte ao modelo pai no Studio.
- Adicione um novo campo do tipo One2many; o Studio pedirá para selecionar o modelo relacionado e o campo Many2one inverso.
- Depois disso, o One2many aparece como uma lista embutida no formulário do pai.
Para muitos utilizadores empresariais, este é o método mais rápido para criar relações One2many sem escrever código; o comportamento é idêntico ao de um campo definido em Python.
Criar por código Python num módulo personalizado
Para desenvolvedores, definir One2many em Python dá controlo total sobre nomeclatura, comportamento e filtros (domain). Um exemplo completo ilustra a criação de ambos os lados da relação:
from odoo import fields, models
class ServiceContract(models.Model):
_name = 'service.contract'
_description = 'Service Contract'
name = fields.Char(string='Contract Name', required=True)
deliverable_ids = fields.One2many(
comodel_name='service.deliverable',
inverse_name='contract_id',
string='Deliverables'
)
class ServiceDeliverable(models.Model):
_name = 'service.deliverable'
_description = 'Service Deliverable'
contract_id = fields.Many2one(
comodel_name='service.contract',
string='Contract',
ondelete='cascade'
)
name = fields.Char(string='Description', required=True)
Repare que o campo Many2one (contract_id) é definido no modelo filho primeiro; o valor de inverse_name no One2many tem de coincidir exactamente com esse nome.
Criar o campo via API XML-RPC
Se gerir campos do Odoo de forma programática em vários ambientes, também é possível criar One2many usando a API XML-RPC sobre o modelo ir.model.fields. A regra mantém‑se: primeiro cria-se o Many2one, depois define-se o One2many referenciando o campo inverso através de relation_field.
Este método é útil para automatizar alterações de esquema em vários sistemas ou para pipelines de deploy que controlem campos dinamicamente.
Boas práticas
A experiência prática com implementações Odoo mostra alguns padrões que reduzem riscos e facilitam manutenção. Seguem-se as recomendações mais valiosas.
- Crie sempre o Many2one primeiro. O One2many não funciona sem o campo inverso existir no modelo filho; isto aplica‑se a Studio, código Python e API.
- Use o sufixo
_idspara os nomes de One2many. É uma convenção do Odoo que torna claro que o campo devolve um recordset (por exemploline_ids,task_ids,deliverable_ids). - Defina
ondelete='cascade'quando for apropriado. Se os filhos devem ser eliminados quando o pai é eliminado, configure isto no Many2one para evitar registos órfãos. - Mantenha a lista embutida focada. Mostre apenas as colunas mais relevantes para não sobrecarregar a vista e prejudicar performance. Utilize atributos opcionais para colunas secundárias que os utilizadores possam activar quando necessário.
- Utilize domain filters para limitar os filhos visíveis. Se o mesmo modelo filho for usado por vários pais, um domain no One2many ajuda a apresentar apenas os registos pertinentes em cada contexto.
- Trate grandes volumes com cuidado. Quando um pai pode ter milhares de filhos, evite carregar tudo de uma só vez numa vista formulário. Considere vistas separadas, paginação ou limites na lista embutida.
Erros comuns a evitar
Eis os erros mais frequentes que se encontram ao trabalhar com One2many, tanto em configuração como no desenvolvimento.
Esquecer o Many2one inverso
O erro mais comum é tentar criar um One2many sem primeiro ter o Many2one no filho. O Odoo vai devolver erro porque o inverse_name não existe. Verifique sempre que o nome indicado realmente existe no modelo filho.
Sintaxe de escrita incorrecta
Para actualizar um One2many via código ou API, deve usar a sintaxe de comandos do Odoo (tuples). Não é possível atribuir uma lista Python simples ao campo. Use os comandos adequados para criar, actualizar ou apagar filhos.
(0, 0, values_dict)cria um novo registo filho.(1, child_id, values_dict)actualiza um registo filho existente.(2, child_id, 0)apaga um registo filho existente (delete).(4, child_id, 0)adiciona um registo filho já existente à relação.(5, 0, 0)desfaz todas as ligações do pai aos filhos sem os eliminar.
Tentar algo como record.line_ids = [1, 2, 3] não funciona — é preciso usar os comandos descritos acima.
Confundir One2many com Many2many
Lembre‑se: One2many implica pertença exclusiva do filho a um pai. Se precisa que o mesmo registo esteja ligado a vários pais ao mesmo tempo, o correto é Many2many. Forçar um One2many nesse cenário leva à duplicação de dados e problemas de integridade.
Problemas de performance com listas extensas
Se um One2many exibe centenas ou milhares de linhas num formulário, o carregamento fica lento — situação habitual em faturas ou movimentos de stock. Use limites nas vistas ou redireccione para uma vista de lista dedicada em vez de carregar tudo inline.
Registos órfãos após eliminação
Apagar um pai sem ter definido ondelete='cascade' no Many2one pode deixar filhos com referência nula, poluindo a base de dados e originando comportamentos inesperados. Defina a política de eliminação de forma clara ao desenhar o modelo de dados.
Conclusão
O One2many é um elemento central do ORM e do modelo de dados do Odoo. Alimenta funcionalidades essenciais — desde linhas de encomenda a linhas de fatura e tarefas de projeto — e, ao compreender a sua dependência do Many2one no filho, fica muito mais simples ler, manter e estender a estrutura do sistema.
Quer esteja a configurar o Odoo para a sua empresa, a personalizá‑lo com Studio ou a desenvolver módulos à medida, o One2many será uma ferramenta recorrente. Saber quando recorrer a ele, como o definir correctamente e como evitar os erros mais comuns poupa tempo e previne problemas de dados no futuro.
Se procura mais tutoriais e guias técnicos sobre campos do Odoo, consulte a colecção Odoo Data & API para artigos complementares e exemplos práticos.
Precisa de ajuda com a sua implementação Odoo?
A Dasolo ajuda empresas a implementar, personalizar e optimizar o Odoo conforme as suas necessidades. Prestamos apoio no desenho de modelos de dados, desenvolvimento de módulos à medida, criação de campos e na valorização da sua solução Odoo atual.
Se tem dúvidas sobre o seu projecto Odoo ou quer aconselhamento sobre a melhor maneira de estruturar os seus dados, contacte‑nose teremos todo o gosto em ajudar.