مقدمة
إذا عملت على أودو لفترة كافية، فمن المرجح أن تواجه رسالة خطأ مزعجة متكررة:
ValueError: Expected singleton
هذا واحد من أشهر أخطاء ORM في أودو. يظهر عندما تتوقّع دالة العمل على سجل واحد بالضبط لكنها تتلقى أكثر من سجل. رغم أن رسالة الخطأ قد تبدو فنية، السبب عادة بسيط عندما تفهم كيف تتعامل أودو مع مجموعات السجلات.
هذا الدليل يوضح معنى خطأ «متوقع سجل مفرد»، الأسباب الشائعة لظهوره، وكيفية إصلاحه بطريقة آمنة دون أن تُخلّ بمنطق العمل أو تكاملات النظام.
ما المقصود بـ «متوقع سجل مفرد» في أودو؟
إطار عمل ORM في أودو لا يتعامل مع كائن مفرد بالعادة، بل مع ما يُسمى مجموعات السجلات التي يمكن أن تكون:
- سجل واحد
- عدة سجلات
- لا سجلات
عندما تنفّذ أودو دالة مصممة للعمل على سجل مفرد لكن مجموعة السجلات تحتوي عدة سجلات، تُثار هذه الاستثناء:
ValueError: Expected singleton
بعبارة بسيطة:
أودو توقّع سجلاً واحداً، لكنه استلم عدة سجلات.
عادةً ما ترى هذا الخطأ في حالات مثل:
- سجلات الخادم (logs)
- دوال الوحدات المخصصة
- حقول محسوبة
- إجراءات الأزرار
- الإجراءات الآلية
- التحديثات الجماعية
فهم سلوك مجموعات السجلات هو المفتاح لإصلاحه بشكل صحيح.
لماذا يظهر هذا الخطأ
1. سوء فهم لمجموعات السجلات
في أودو، المتغير self في الغالب هو مجموعة سجلات.
حتى لو اعتقدت أنك تتعامل مع سجل واحد، قد تستدعي أودو دالتك على أكثر من سجل أثناء:
- عمليات الدفع على واجهة القوائم (tree) لمجموعة من السجلات
- سير عمل آلي
- إجراءات الخادم
- استيراد عبر API
إذا فرض كودك أنه يعمل على سجل واحد فقط فسيفشل عند معالجة عدة سجلات.
2. غياب حلقة تكرار داخل الدالة
مثال على كود يسبب المشكلة:
def action_confirm(self): self.state = 'confirmed'
إذا احتوت self على سجلات متعددة، يظهر التداخل واللبس.
الطريقة الصحيحة:
def action_confirm(self): for record in self: record.state = 'confirmed'
3. الاستخدام الخاطئ لـ ensure_one()
أودو يوفّر أداة:
self.ensure_one()
تجبر الدالة على أن تعمل على سجل واحد فقط. إن وُجدت سجلات متعددة، ستطرح استثناء singleton عمداً.
استعملها فقط عندما يقتضي منطق العمل وجود سجل مفرد بلا بديل (مثلاً عند فتح نموذج تحرير).
4. استعلام search يعيد عدة سجلات
مثال:
partner = self.env['res.partner'].search([('name', '=', 'John')])
إذا وُجدت عدة سجلات باسم «John»، وأمثلتك التالية تتوقع واحداً فقط، سيظهر الخطأ.
بديل آمن:
partner = self.env['res.partner'].search([('name', '=', 'John')], limit=1)
5. غموض الحقول العلائقية
الأخطاء كثيراً ما ترتبط بعلاقات Many2one أو One2many.
مثال:
self.order_line.product_id.name
إذا احتوت order_line على عدة عناصر، يصبح التعبير غير محدد.
كيفية إصلاح خطأ Expected Singleton
الخطوة 1 – كرّر على مجموعات السجلات
قانون افتراضي في أودو:
افترض دائماً أن self قد تحتوي على سجلات متعددة.
for record in self: record.process_logic()
الخطوة 2 – استخدم limit=1 عند الحاجة فقط
عندما يكون منطق العمل منطقيًا أنه سجل واحد:
record = self.env['model.name'].search(domain, limit=1)
الخطوة 3 – تحقّق من الحقول العلائقية
راجع:
- علاقات Many2one
- تجميعات One2many
- معايير (دومين) البحث
تأكّد من أنك لا تعمل عن غير قصد على صفوف متعددة.
الخطوة 4 – راجع واجهات API وعمليات الاستيراد
في بيئاتٍ متصلة بكثافة، العمليات الدُفعية غالباً ما تُطلق هذا الخطأ لأن عدة سجلات تُعالَج دفعة واحدة.
إذا كانت نسختك من أودو تُزامِن بيانات من أنظمة خارجية، صمّم منطقًا يقبل الدُفعات بأمان.
كيفية تجنّب هذا الخطأ في تطوير أودو المستقبلي
- تجنّب افتراض سياق سجل مفرد
- اختبر الدوال على سجلات متعددة محددة
- استخدم حلقات التكرار بشكل افتراضي
- أضف limit=1 بوعي عند الحاجة
- نظّم الحقول العلائقية بوضوح
في إعدادات التكامل المعقدة، تظهر أخطاء كهذه عادةً أثناء الاستيرادات الآلية أو الوظائف المجدولة. تصميم دوال آمنة للدُفعات يمنع عدم استقرار النظام.
كيف تتعامل Dasolo مع أخطاء سجلّات ORM
خطأ «متوقع سجل مفرد» نادراً ما يكون مجرد هفوة برمجية بسيطة؛ في بيئات أودو المنظّمة يكشف هذا الخطأ عن افتراضات أعمق حول سلوك مجموعات السجلات، استخدام ORM، وتدفق البيانات.
في Dasolo نتعامل مع أخطاء ORM بمراجعة شاملة لكيفية معالجة مجموعات السجلات طوال دورة حياة الوحدة. غالباً ما تنشأ مشكلات السجل المفرد عندما يُكتب منطق الأعمال ليتعامل مع سجل واحد لكن يُنفّذ على مجموعات متعددة، خاصة في التدفقات الآلية أو التكاملات أو الحقول المحسوبة.
لمنع تكرار أخطاء singleton نركّز على:
- أنماط تكرار صريحة لمجموعات السجلات
- استخدام آمن لـ ensure_one()
- تصفية دومينات قابلة للتوقّع
- بنية علاقات نظيفة
- تحكم دقيق بمحفزات الأتمتة
تصميم منطق ORM قابل للتوسع يقلّل بشكل كبير من الأخطاء المفاجئة أثناء التشغيل في أنظمة الإنتاج.
خاتمة
خطأ Odoo «Expected Singleton» هو استثناء شائع يحدث عندما يحاول الكود العمل على سجلات متعددة بينما يتوقع واحداً فقط. رغم أنه قد يبدو كخطأ بسيط للمطوّر، إلا أنه غالباً ما يشير إلى عدم تجانس في طريقة التعامل مع مجموعات السجلات داخل وحدات مخصصة أو عمليات آلية.
بفهم كيفية إدارة أودو لمجموعات السجلات وتبني أنماط تكرار آمنة، يمكن للمطوّرين منع تكرار هذا الخطأ. التعامل المنظم مع السجلات، التحققات الصريحة، ومنطق أتمتة محسوب هي عناصر أساسية للحفاظ على استقرارية نشرات أودو.
عند معالجتها بشكل صحيح، تتحول أخطاء singleton إلى إشارات مفيدة تساعدك على تقوية جودة الكود وموثوقية النظام على المدى الطويل.
الأسئلة الشائعة
لا. يظهر في أودو 14 و15 و16 و17.
لا. هو مشكلة منطقية في كيفية معالجة السجلات.
لا. استعملها فقط عندما يتطلّب منطق الأعمال تنفيذ الدالة على سجل واحد بالتحديد.