إذا قضيت وقتًا في تعديل واجهات أودو أو التعامل مع الـ ORM فحتماً واجهت مصطلح context. ستجده مرتبطًا بتعريفات الحقول، بسمات الـ XML للواجهات، وبالدوال في كود بايثون. بالنسبة لكثير من المطورين والاستشاريين يبقى الـ context شيئًا يعمل ضمنيًا — إلى أن يتسبب بمشكلة مفاجئة.
فهم كيف تعمل حقول الـ context في أودو ليس رفاهية نظرية؛ بل له أثر مباشر على سلوك النموذج: كيف تُملأ النماذج تلقائيًا، كيف تُصفى النتائج، وكيف تُحتسب الحقول المحسوبة. سواء كنت تقوم بتخصيص بسيط أو تبني وحدة كاملة، التعامل السليم مع الـ context يوفر عليك كثيرًا من ساعات التصحيح.
هذا الدليل يوضح مفهوم الـ context، كيف يتحرك داخل إطار عمل أودو، ومتى تستخدمه بطريقة عملية في مشاريع حقيقية.
ما هي فكرة الـ Context في أودو؟
في جوهره، الـ Context في أودو عبارة عن قاموس بايثون يرافق كل نداء، كل عملية على سجل، وكل تفاعل مع الواجهة. ليس نوعًا من الحقول في الـ ORM، لذلك لن تجد fields.Context(). هو آلية تُغيّر سلوك الحقول والعمليات دون أن تكون عمودًا في قاعدة البيانات.
تخيّله كمجموعة تعليمات غير مرئية تُحمل مع الطلب: تخبر أودو ما إذا كان ينبغي تعبئة حقل افتراضيًا، أن تُظهر سجلات مُؤرشفة، أن تستخدم لغة معينة للحسابات، أو أن تطبّق نطاقًا عند عرض مُختار السجلات المرتبطة.
أين يظهر الـ Context
ستصطدم بالـ context في ثلاثة مواضع رئيسية داخل نموذج بيانات أودو:
- في تعريفات الحقول ببايثون: يُستخدم الباراميتر
contextمع الحقول العلائقية مثل Many2one، One2many، وMany2many. - في سمات واجهات XML: سمة
contextعلى وسم<field>في نماذج form، list، وkanban. - في بيئة الـ ORM: الوصول إلى القاموس عبر
self.env.context، وتعديله عبرself.with_context(key=value).
في كل الحالات الثلاث، يقوم الـ context بنفس الدور الأساسي: حمل معلومات إضافية تُحدِّد سلوك الحقل أو السجل عند تنفيذ العملية.
كيف يتصرف الـ Context داخل نموذج بيانات أودو
الـ Context يتتبع دورة طلب المستخدم من فتح النموذج حتى حفظ السجل. فيما يلي كيفية عمل الآليات الرئيسية عمليًا.
القيم الافتراضية عبر مفتاح default_*
نمط شائع جدًا هو استخدام مفاتيح تبدأ بـ default_. أي مفتاح بهذا الشكل يُستخدم لتعبئة الحقل عند إنشاء سجل جديد.
مثال عملي: إذا ضغط المستخدم زرًا لفتح نموذج طلب مبيعات وتم تمرير {"default_partner_id": 42} في السياق، فلن يحتاج المستخدم لاختيار العميل يدوياً لأن حقل العميل سيكون قد عُيّن مسبقًا إلى الشريك رقم 42.
هذا الأسلوب منتشر في تخصيص أودو لبناء تدفقات تنقل ذكية بين السجلات دون كود إضافي.
سمة context على الحقول العلائقية
عند تعريف حقل Many2one أو One2many أو Many2many في بايثون يمكنك تمرير باراميتر context. هذا السياق يُطبّق كلما تم فتح اختيار سجل عبر القوائم المنسدلة أو إنشاء سجل من داخل الحقل.
توضيح عملي: حقل Many2one إلى res.partner مع context={"default_is_company": True} يجعل مربع "شركة" محددًا تلقائيًا عند إنشاء شريك جديد من ذلك الحقل — توجيه لطيف للمستخدمين دون فرض القاعدة.
الـ Context داخل XML للواجهات
في XML، سمة context على وسم الحقل تعمل بالمبدأ نفسه لكنها يمكن أن تكون ديناميكية عبر تعابير تقييم أودو:
هذا يمكّنك من تصميم نماذج ذكية حيث يتغيّر سياق حقل بناءً على قيمة حقل آخر — تقنية أساسية في تخصيص أودو لتقليل الكود وتحسين تجربة المستخدم.
قراءة وتعديل الـ Context في بايثون
داخل أي ميثود في الموديل يمكنك الاطلاع على السياق الحالي عبر self.env.context، وهو القاموس كما وصل عند استدعاء الميثود.
لتنفيذ كود بسياق معدل تستخدم self.with_context(key=value)؛ هذا يعيد recordset جديد يحمل السياق المحدّث دون تغيير البيئة الأصلية — نمط نظيف وغير مدمر يتماشى مع فلسفة أودو.
مفاتيح السياق المدمجة الشائعة
أودو يستعمل بعض مفاتيح السياق المحجوزة التي تُغيّر سلوك الإطار في أمثلة متعددة:
lang: يبدّل اللغة المستخدمة في القيم المترجمة.active_test: ضبطها علىFalseيسمح بإظهار السجلات المؤرشفة في نتائج البحث.no_recompute: يمنع إعادة حساب الحقول المحفوظة.mail_notrack: يعطّل تتبع التغييرات في الشاتَر عند عملية كتابة.allowed_company_ids: يتحكم برؤية السجلات في بيئات تعدد الشركات.bin_size: يعيد أحجام الملفات بدل المحتوى الثنائي لحقل Binary.
معرفة هذه المفاتيح جزء لا يتجزأ من أي دليل مطور أودو لأنها تتيح التحكم دون كتابة كود مخصّص.
أمثلة عملية من الحياة المهنية
الـ Context ليس حكراً على المطورين؛ بل يحل مشاكل سير العمل في مجالات نشاط مختلفة. فيما يلي خمسة استخدامات عملية شائعة في مشاريع أودو.
1. إدارة المبيعات: تعبئة فريق المبيعات تلقائيًا عند إنشاء عملاء محتملين
مدير مبيعات يعمل على كانبان مُفلتر على فريقه؛ عند الضغط على "جديد" يتوقع أن يُنسب العميل المحتمل لذلك الفريق. تمرير default_team_id في السياق يوفّر هذه التجربة دون تدخل يدوي.
2. عروض الأسعار: تحديد قائمة الأسعار حسب فئة العميل
عند فتح عرض سعر من قائمة عملاء بفئة معينة، يمكن تمرير default_pricelist_id عبر السياق لتوجيه مندوب المبيعات إلى قائمة الأسعار المناسبة دون إجباره على اختيارها.
3. المخزون: تقييد المواقع في نماذج النقل
في عمليات المستودع يمكن لحقول الموقع المصدر استخدام السياق لعرض مواقع تخص مخزن معين فقط—بذلك تبقى القوائم أنظف وتقل الأخطاء في بيئات متعددة المستودعات.
4. المحاسبة: خطوط الفاتورة متعددة اللغات
عند إنشاء فاتورة لعميل دولي، مفتاح السياق lang يضمن أن تظهر الأوصاف بلغة العميل، حتى لو كانت قاعدة البيانات تُخزن النصوص بلغة داخلية مختلفة.
5. نماذج مخصصة: عرض المنتجات المؤرشفة في رؤية خاصة
فريق العمليات يحتاج مراجعة منتجات متوقفة إلى جانب النشطة؛ تمرير active_test: False في سياق عرض مخصص يسمح بعرض جميع المنتجات في تلك القائمة فقط، دون تغيير السلوك الافتراضي للنظام.
إضافة وتخصيص السياق على الحقول
هناك طريقتان لإضافة أو تعديل السياق على الحقول: استخدام Odoo Studio بدون كود، أو كتابة بايثون وXML للتحكم الكامل — خطوة أساسية في أي درس تقني لأودو حول سلوك الحقول.
استخدام Odoo Studio
يتيح لك Odoo Studio تعديل خصائص الحقول دون كتابة كود. بالنسبة للحقول العلائقية يعرض خيارًا لتعيين سياق بسيط يملأ قيمًا افتراضية عند إنشاء سجل من داخل الحقل.
هذا مناسب للحالات المباشرة: تعبئة الشركة، الفريق، الفئة، أو المسؤول. لكن دعم Studio للسياق مبسّط عمدًا؛ إذا احتجت سياقًا ديناميكيًا يعتمد على قيم حقول أخرى فستحتاج للتخصيص الفني.
عند استخدام حقول Studio تذكر أن السياق المخزن يُحفظ على العرض نفسه. فإذا أضفت لاحقًا تخصيصًا تقنيًا لنفس العرض، فراجع سياقات Studio لتفادي تعارضات.
تعريف السياق على الحقول ببايثون
في وحدة مخصّصة تضيف السياق مباشرة في تعريف الحقل. لحقل Many2one، يقبل باراميتر context قاموسًا ثابتًا:
مثل هذا السياق الثابت يُطبّق في كل مرة يُحمّل أو يُنشأ فيها سجل مرتبط. لا يتغير وفقًا لحالة السجل الحالية؛ إذا احتجت سلوكًا تفاعليًا استعمل سياق العرض (XML).
تعريف السياق في XML للواجهات
في XML يقبل باراميتر context نصًا تُقيّمه أودو وقت التشغيل. يمكنك الإشارة إلى قيم الحقول، معرف المستخدم (uid), المعرف النشط (active_id)، ومتغيرات أخرى:
هذا يجعل سياق العرض أكثر مرونة من سياق الحقل الثابت. هو الأسلوب القياسي داخل إطار أودو لبناء نماذج يتغير سلوك حقل فيها حسب حقل آخر — وبه تبني سلوكيات واجهة تبدو طبيعية للمستخدمين.
تمرير السياق عبر إجراءات النوافذ (Window Actions)
يمكن أيضًا تحديد السياق على سجلات ir.actions.act_window. هكذا تمر القوائم والأزرار السياق إلى العرض الذي تفتحه. حقل context في الإجراء يُدمج مع السياق الجلسي عندما يُحمّل العرض.
هذا الأسلوب مناسب لحالات مثل مثال فريق المبيعات في CRM: السياق موجود على الإجراء وليس على الحقل، ما يتيح افتراضات مختلفة حسب نقطة الدخول دون تعديل الكود النموذجي.
ممارسات موصى بها
التعامل مع الـ context يصبح أكثر انتظامًا عندما تتبع عادات واضحة سواء كنت تطور وحدة أو تجري تخصيصًا سريعًا.
- استخدم السياق كاقتراحات لا كقواعد ملزمة. الافتراضات في السياق ترشد المستخدمين لكنها لا تمنعهم. إذا أردت قيدًا حقيقيًا استعمل domain أو منطق onchange.
- ضع السياق الديناميكي في الواجهات ولا تخرطه في تعريف الحقول. سياق الحقل ثابت؛ أما إذا احتجت استجابة لحالة السجل فالأفضل اعتماده في XML.
- استخدم
with_context()بدل محاولة تغييرenv.contextمباشرة. بيئة أودو صُممت لتكون غير قابلة للتغيير ضمن الاستدعاء، وwith_context تنشئ بيئة جديدة بسلاسة. - كن متعمداً فيما تمرره في السياق. المفاتيح تتراكم عبر سلسلة الاستدعاءات؛ إضافة مفاتيح غير ضرورية قد يؤدي لسلوك مفاجئ في دوال تتحقق من هذه المفاتيح.
- استخدم السياق لتمرير علامات تُتحقق لاحقًا. نمط شائع هو تمرير علامة منطقية مثل
from_wizard: Trueثم التحقق منها داخل حساب أو onchange لتغيير السلوك بدون إضافة حقول حالة إلى النموذج. - وثّق مفاتيح السياق المخصصة داخل وحدتك. مفاتيح السياق غير مرئية للمطور الذي لا يعرف بوجودها، لذا تعليق أو docstring يشرح المفاتيح المخصصة يوفر وقتًا لاحقًا.
مشاكل شائعة وسببها
أخطاء متعلقة بالسياق قد تكون صعبة التتبّع لأن السياق لا يظهر في الواجهة. هذه بعض الأخطاء المتكررة في المشاريع الواقعية.
اعتبار default_* كقيمة إجبارية
قيمة افتراضية عبر السياق تُطبّق فقط عند إنشاء السجل من نموذج؛ إذا أنشأت السجلات برمجيًا عبر ORM دون تمرير السياق المناسب فلن تُطبّق تلك القيم. كثير من المطورين يتوقعون سلوكًا مماثلًا لباراميتر default في التعريف — وهذا غير صحيح. مرّر السياق صراحةً عند إنشاء السجلات بالبرمجة إذا كانت تلك القيم مهمة.
تعديل قاموس السياق مباشرة
قاموس السياق يُشارك عبر سلسلة الاستدعاءات؛ إذا عدّلت self.env.context مباشرة فقد تؤثر على كود آخر يعمل في نفس المعاملة. النمط الصحيح هو self.with_context(new_key=value) لإنشاء بيئة جديدة مع نسخة معدّلة من السياق.
تمرير الكثير من المفاتيح في السياق
كل مفتاح تضيفه يسافر عبر سلسلة الاستدعاءات. بعض دوال أودو تتفقد مفاتيح محددة وتغير سلوكها؛ تمرير مفاتيح غير متوقعة قد يفعل فروعًا في الكود بلا قصد. اجعل السياق مُركّزًا ومحدودًا لحاجة العملية.
نسيان active_test عند البحث عن السجلات المؤرشفة
افتراضيًا، search() وsearch_read() يستبعدان السجلات المؤرشفة (حيث active = False). إذا كنت تحتاج التعامل مع السجلات المؤرشفة فعليك تمرير active_test: False في السياق؛ نسيان هذا السبب شائع لأخطاء في خصائص المنتجات والمخزون.
تعارضات سياق بين Studio والكود المخصص
إذا قام Odoo Studio بتعيين سياق لحقل وفيما بعد أضفت توسيعًا تقنيًا (view inheritance) يستهدف نفس الحقل فقد تتعارض السياقات أو يطغى أحدها حسب ترتيب الدمج في XML. افحص السياقات الموجودة قبل إضافة سياق جديد خاصة عند المزج بين حقول Studio وتخصيصات الوحدات.
خلاصة
الـ Context آلية صامتة لكنها تؤدي وظائف كثيرة داخل أودو. عندما تفهم كيف ينتقل بين تعريف الحقول، سمات الواجهات، وبيئة الـ ORM تحصل على قدرة تحكم أدق في سلوك نموذج البيانات.
خلاصة النقاط المهمة: استخدم مفاتيح default_* لتوجيه المستخدمين دون إجبارهم، ضع السياق الديناميكي في الواجهات لا في تعريف الحقول، اعتمد with_context() بدل تعديل السياق مباشرة، وحافظ على السياق مختصرًا لتجنب التداخلات غير المقصودة.
سواء كنت تتابع درس حقول أودو، تطور وحدة مخصصة، أو تصلح سلوك حقل غريب، فهم الـ context سيكون جزءًا أساسيًا من الحل.
في Dasolo نساعد الشركات على تنفيذ وتخصيص وتحسين أودو ليتوافق مع سير عملها الحقيقي. إن كنت تعمل على تخصيص يتضمن سياقًا ولست متأكدًا من صحته، أو ترغب بمناقشة تنفيذك في أودو، يسعدنا المساعدة.
تواصل مع فريقنا عبر صفحة الاتصال وأخبرنا بما تبنيه. نعمل مع مؤسسات بمختلف الأحجام لنضمن أن أودو يعمل بالطريقة الصحيحة.