Introduktion
Hvis du har arbejdet med Odoo længe nok, har du sandsynligvis stødt på den velkendte:
ValueError: Expected singleton
Denne fejl tilhører de hyppigste ORM-problemer i Odoo. Den opstår, når en funktion forventer præcis én post, men i stedet får flere. Selvom fejlnavnet virker teknisk, er årsagen ofte ret ligetil, når du forstår, hvordan Odoo håndterer recordsets.
Denne guide gennemgår, hvad “Expected Singleton” betyder, hvorfor den opstår, og hvordan du retter den uden at ødelægge forretningslogik eller integrationer.
Hvad betyder “Expected Singleton” i Odoo?
Odoos ORM (Object Relational Mapping) arbejder ikke med enkelte objekter som standard. I stedet bruges recordsets, som kan indeholde:
- Én post
- Flere poster
- Ingen poster
Når Odoo kalder en metode, der er lavet til at arbejde med én post, men recordset’et indeholder flere, kastes der:
ValueError: Expected singleton
Kort sagt:
Odoo forventede én post. Den fik flere.
Fejlen dukker typisk op i:
- Serverlogs
- Egne moduler
- Beregnede felter (computed fields)
- Knap-handlinger
- Automatiske handlinger
- Bulk-opdateringer
Forståelse af recordset-adfærd er nøglen til en korrekt løsning.
Hvorfor opstår denne fejl?
1. Forkert forståelse af recordsets
I Odoo er self i praksis næsten altid et recordset.
Selvom du tror, du arbejder med én post, kan Odoo kalde din metode for flere poster i forbindelse med:
- Batch-operationer i listevisninger
- Automatiserede workflows
- Server-handlinger
- API-importer
Hvis din kode antager én post, vil den fejle, når der behandles flere.
2. Manglende løkke i en metode
Eksempel på problematisk kode:
def action_confirm(self): self.state = 'confirmed'
Hvis self indeholder flere poster, opstår tvetydighed.
Korrekt tilgang:
def action_confirm(self): for record in self: record.state = 'confirmed'
3. Forkert brug af ensure_one()
Odoo tilbyder:
self.ensure_one()
Det tvinger metoden til at arbejde med præcis én post. Hvis der er flere, kastes singleton-fejlen med vilje.
Brug det kun, når forretningslogikken strengt kræver én post (fx ved åbning af en formular).
4. Søgning returnerer flere poster
Eksempel:
partner = self.env['res.partner'].search([('name', '=', 'John')])
Hvis der findes flere "John"-poster, og efterfølgende kode forventer kun én, opstår fejlen.
Sikrere alternativ:
partner = self.env['res.partner'].search([('name', '=', 'John')], limit=1)
5. Ambiguitet i relationsfelter
Fejl involverer ofte Many2one eller One2many-relationer.
Eksempel:
self.order_line.product_id.name
Hvis order_line indeholder flere linjer, bliver udtrykket tvetydigt.
Sådan retter du fejlen Expected Singleton
Trin 1 – Loop over recordsets
Grundregel i Odoo:
Antag altid, at self kan indeholde flere poster.
for record in self: record.process_logic()
Trin 2 – Brug limit=1 når det er påkrævet
Når kun én post logisk giver mening:
record = self.env['model.name'].search(domain, limit=1)
Trin 3 – Valider relationsfelter
Tjek:
- Many2one-relationer
- One2many-samlinger
- Domænefiltre
Sørg for, at du ikke utilsigtet arbejder med flere rækker.
Trin 4 – Gennemgå API- eller importprocesser
I miljøer med mange integrationer udløser bulk-operationer ofte denne fejl, fordi flere poster behandles samtidig.
Hvis din Odoo-instans synkroniserer data fra eksterne systemer, skal du sikre, at logikken er batch-sikker.
Sådan forebygger du fejlen i fremtidig Odoo-udvikling
- Undgå at antage kontekst med enkeltpost
- Test metoder med flere valgte poster
- Brug løkker som standard
- Tilføj limit=1 med omtanke
- Strukturer relationsfelter tydeligt
I komplekse integrationsscenarier dukker denne type fejl ofte op under automatiske imports eller planlagte jobs. Metoder, der er designet til batch-behandling, forebygger ustabilitet.
Hvordan Dasolo håndterer recordset- og ORM-fejl
“Expected Singleton” er sjældent blot en enkelt kodningsfejl. I velstrukturerede Odoo-miljøer afslører den ofte dybere antagelser om recordset-adfærd, ORM-brug og datakonsistens.
Hos Dasolo angriber vi ORM-fejl ved at gennemgå, hvordan recordsets håndteres gennem hele modulernes livscyklus. Singleton-problemer opstår typisk når forretningslogik er skrevet til enkeltposter, men udføres på sæt af poster—særligt i automatiseringer, integrationer eller beregnede felter.
For at undgå gentagne singleton-fejl fokuserer vi på:
- Klare mønstre for iteration over recordsets
- Sikker brug af ensure_one()
- Forudsigelige domænefiltre
- Ren relationsarkitektur
- Kontrollerede automations-triggere
At designe ORM-logik med skalerbarhed for øje reducerer uventede runtime-fejl i produktionssystemer.
Konklusion
Odoo-fejlen “Expected Singleton” er en almindelig ORM-undtagelse, der opstår, når kode forsøger at arbejde med flere poster, mens den forventer kun én. Selvom det kan virke som en simpel udviklerfejl, kan den pege på mere grundlæggende uoverensstemmelser i recordset-håndtering eller automatiserede processer.
Ved at forstå, hvordan Odoos ORM behandler recordsets, og ved at anvende sikre iterationsmønstre, kan udviklere forhindre, at fejlen gentager sig. Struktureret håndtering af poster, eksplicit validering og kontrolleret automation er nøglen til stabile Odoo-installationer.
Når singleton-fejl håndteres korrekt, bliver de et nyttigt signal, der hjælper med at styrke kodekvalitet og langsigtet systemstabilitet.
Ofte stillede spørgsmål
Nej. Den findes i Odoo 14, 15, 16 og 17.
Nej. Det er et logisk problem i måden, poster håndteres på.
Nej. Kun når forretningslogikken absolut kræver eksekvering på en enkelt post.