تطوير أودو

كيفية عرض صورة في QWeb أودو — الويب والتقارير والبوابة (أودو 16–19)

مرجع شامل للمطوّر لعرض الصور في قوالب QWeb لأودو: وحدة التحكم /web/image وأنماط t-att-src وt-field widget='image' وصور تقارير PDF واستكشاف الأخطاء الشائعة. موثق لأودو 18 و19.

iWesabe Editorial Team١ سبتمبر ٢٠٢٠7 دقائق للقراءة

يعتمد عرض الصور في QWeb أودو على المكان الذي يعمل فيه القالب وكيفية تخزين الصورة. تتطلب صفحة الويب وقالب البوابة وتقرير PDF وقالب البريد الإلكتروني كل منها نهجًا مختلفًا. أهم التمييزات: يمكن للقوالب المعروضة على الويب استخدام عناوين URL (وحدة التحكم `/web/image`)، بينما تتطلب قوالب تقارير PDF بيانات ثنائية مشفرة بـ base64 لأن محرك wkhtmltopdf لا يملك وصولًا للشبكة إلى خادم أودو وقت العرض.

طرق عرض الصور — متى تستخدم كل منها

طرق عرض صور QWeb حسب السياق
الطريقةسياق القالبمصدر الصورةملاحظات
رابط /web/image + t-att-srcالموقع الإلكتروني والبوابة وعروض الويب والبريد الإلكتروني (إرسال خارجي)حقل Binary/Image على أي نموذجالأكثر مرونة. يخدم أودو الصورة عبر HTTP. يدعم معاملات تغيير الحجم.
t-field widget='image'تقارير PDF (qweb-pdf) فقطحقل Binary/Imageيعرض قيمة الحقل كوسم img مضمّن بـ base64. مطلوب لـ PDF — لا يستطيع wkhtmltopdf جلب عناوين URL.
أصل ثابت (t-att-src مع /web/static/)أي قالب QWebملف في دليل static/src/ للوحدةللصور المجمّعة مع الوحدة (الشعارات والأيقونات). المسار: /web/static/src/<module>/img/<file>.
base64 مضمّن (t-att-src مع URI بيانات)تقارير PDF وقوالب البريد الإلكترونيسلسلة base64 محسوبة في Pythonبديل عندما لا يكون t-field متاحًا أو للصور المحسوبة ديناميكيًا.

الجزء 1 — وحدة التحكم /web/image (الويب والبوابة)

وحدة التحكم `/web/image` هي نقطة نهاية HTTP المدمجة في أودو لتقديم قيم الحقول الثنائية كصور. تتولى التخزين المؤقت والتحكم في الوصول (مع احترام قواعد السجلات) وتغيير الحجم الاختياري على جانب الخادم. هذه هي الطريقة الصحيحة لأي قالب معروض على الويب — صفحات الموقع وقوالب البوابة وبطاقات Kanban وودجات عرض النماذج والبريد الإلكتروني الخارجي.

صيغة رابط /web/image

text
# Basic form — model + record ID + field name
/web/image/<model>/<id>/<field>

# With optional width/height resize
/web/image/<model>/<id>/<field>/<width>x<height>

# Using record external ID instead of integer ID
/web/image/<model>/<external_id>/<field>

# Examples:
/web/image/res.partner/42/image_1920
/web/image/product.product/7/image_1920/128x128
/web/image/res.company/1/logo

أنماط t-att-src في قوالب QWeb

xml
<!-- Pattern 1: Image field on the current record (e.g. inside t-foreach or a record template) -->
<img t-att-src="'/web/image/%s/%s/image_1920' % (object._name, object.id)"
     alt="Partner Image"
     style="max-width: 200px;"/>

<!-- Pattern 2: Specific model + ID (hardcoded or from a Python variable) -->
<img t-att-src="'/web/image/res.partner/' + str(partner.id) + '/image_1920'"
     alt="Partner"/>

<!-- Pattern 3: With server-side resize (128×128 thumbnail) -->
<img t-att-src="'/web/image/product.product/%d/image_1920/128x128' % product.id"
     alt="Product thumbnail"/>

<!-- Pattern 4: Company logo in a header -->
<img t-att-src="'/web/image/res.company/%d/logo' % company.id"
     alt="Company Logo"
     style="height: 60px;"/>

<!-- Pattern 5: Conditional — only render img if the field has a value -->
<img t-if="partner.image_1920"
     t-att-src="'/web/image/res.partner/%d/image_1920' % partner.id"
     alt="Partner Image"/>

الجزء 2 — الصور في تقارير QWeb PDF

تُنشأ تقارير PDF في أودو بواسطة wkhtmltopdf، الذي يُعيد تصيير قالب QWeb بتنسيق HTML ويحوّله إلى PDF. القيد الحاسم: يعمل wkhtmltopdf كعملية منفصلة ولا يستطيع إجراء طلبات HTTP إلى خادم أودو. أي `` في تقرير PDF سيُفضي إلى صورة معطلة. الحل هو `t-field` مع `widget='image'`، الذي يوجّه أودو لعرض قيمة الحقل كـ URI بيانات base64 مضمنة قبل تمرير HTML إلى wkhtmltopdf.

xml
<!-- CORRECT: t-field with widget='image' for PDF reports -->
<t t-foreach="docs" t-as="o">

  <!-- Company logo in report header -->
  <img t-field="o.company_id.logo"
       t-options="{'widget': 'image', 'class': 'company_logo'}"
       style="max-height: 60px;"/>

  <!-- Product image in report line -->
  <td>
    <img t-field="o.product_id.image_128"
         t-options="{'widget': 'image'}"
         style="width: 64px; height: 64px;"/>
  </td>

  <!-- Partner photo — only if present -->
  <t t-if="o.partner_id.image_1920">
    <img t-field="o.partner_id.image_1920"
         t-options="{'widget': 'image', 'class': 'partner_photo'}"
         style="width: 100px;"/>
  </t>

</t>

<!-- WRONG (broken image in PDF): -->
<!-- <img t-att-src="'/web/image/res.partner/%d/image_1920' % o.partner_id.id"/> -->

الجزء 3 — الصور الثابتة للوحدة (الشعارات والأيقونات)

للصور التي تكون جزءًا من وحدتك (غير مخزنة في قاعدة البيانات) — مثل شعار افتراضي أو علامة مائية أو رسم زخرفي — خزّنها في `static/src/img/` وأشر إليها بمسار ثابت. تعمل هذه المسارات في قوالب الويب وتقارير PDF لأن wkhtmltopdf يمكنه حل مسارات نظام الملفات المحلية.

xml
<!-- Static module image in any QWeb template (web OR PDF report) -->

<!-- Method A: absolute web path -->
<img src="/my_module/static/src/img/logo.png"
     alt="My Module Logo"
     style="height: 50px;"/>

<!-- Method B: t-att-src with module path concatenation -->
<img t-att-src="'/my_module/static/src/img/' + image_filename"
     alt="Dynamic static image"/>

<!-- Method C: using report_logo (Odoo built-in for PDF headers) -->
<!-- In ir.actions.report, set print_report_name and use the
     built-in 'web.base_layout' which already includes the company logo. -->

تعريف حقول الصور في نماذج Python

python
from odoo import models, fields

class MyModel(models.Model):
    _name = 'my.model'

    # fields.Image — recommended for Odoo 13+
    # Automatically stores multiple resolution copies (1920/1024/512/256/128)
    # when max_width/max_height are set. Stored as base64 in the database.
    image = fields.Image(
        string='Image',
        max_width=1920,
        max_height=1920,
    )

    # fields.Binary with attachment=True — for large files or non-image binaries
    # Does NOT auto-generate resized copies.
    # Store in filestore (not database column) with attachment=True.
    document = fields.Binary(
        string='Document',
        attachment=True,
    )

    # For an image that must also have thumbnail variants:
    image_1920 = fields.Image('Image', max_width=1920, max_height=1920)
    image_128 = fields.Image('Image (128)', related='image_1920',
                              max_width=128, max_height=128, store=True)

استكشاف الأخطاء

مشكلات صور QWeb الشائعة وحلولها
الأعراضالسبب المحتملالحل
أيقونة صورة معطلة في تقرير PDFاستخدام رابط /web/image مع t-att-src داخل تقرير qweb-pdf — لا يستطيع wkhtmltopdf جلب الرابطاستبدل t-att-src بـ t-field و t-options="{'widget': 'image'}" على حقل binary/image.
تظهر الصورة في المتصفح لكن ليس في PDFنفس السبب أعلاه — t-att-src يعمل في المتصفح لكن يفشل في PDFاستخدم t-field مع widget='image' لتقارير PDF. احتفظ بـ t-att-src لقوالب الويب/البوابة.
/web/image يُعيد 404معرّف السجل أو اسم الحقل في الرابط خاطئ، أو المستخدم لا يملك صلاحية قراءة السجلتحقق من اسم النموذج ومعرّف السجل واسم الحقل. تأكد أن قواعد سجلات المستخدم تسمح بقراءة السجل. في وضع المطوّر، اختبر الرابط مباشرةً في المتصفح.
تظهر الصورة لكن بجودة منخفضة / صغيرة جدًااستخدام حقل image_128 أو image_512 عندما يتطلب حجم العرض دقة أكبراستخدم image_1920 للمناطق الكبيرة واخفّض الحجم بـ CSS max-width. أو استخدم لاحقة تغيير الحجم في /web/image: /web/image/model/id/field/400x300.
t-field widget='image' يُظهر نص base64 الخام بدلًا من صورةنوع الحقل هو fields.Char أو fields.Text، وليس fields.Binary أو fields.Imageغيّر نوع الحقل إلى fields.Image أو fields.Binary. t-field widget='image' يعمل فقط مع أنواع حقول Binary/Image.
تظهر الصورة في قالب البوابة للمسؤول لكن ليس لمستخدم البوابةقاعدة سجل على النموذج تمنع مستخدم البوابة من قراءة السجل الذي يحتوي على الصورةتحقق من قواعد السجلات على النموذج. وحدة التحكم /web/image تحترم حقوق الوصول — إذا لم يتمكن المستخدم من قراءة السجل، فلن يرى الصورة. أضف قاعدة سجل لمستخدم البوابة أو استخدم sudo() بحذر في متحكم مخصص.

ملاحظات الإصدار

تغييرات عرض صور QWeb حسب إصدار أودو
إصدار أودوالتغييرات الرئيسية المؤثرة على عرض الصور
أودو 15fields.Image مستقرة. سلوك وحدة التحكم /web/image وt-field widget='image' لم يتغير منذ أودو 13/14. لا يزال wkhtmltopdf مستخدمًا لإنشاء PDF.
أودو 16لا توجد تغييرات كاسرة على عرض الصور. يُضيف أودو 16 دعم WebP إلى fields.Image (مخزنة بتنسيق WebP عندما يكون المصدر WebP). تُقدّم /web/image صيغة WebP للمتصفحات التي تدعمها.
أودو 17لا توجد تغييرات كاسرة. t-field widget='image' لم يتغير. /web/image لم تتغير. إنشاء PDF لا يزال يستخدم wkhtmltopdf. يُحسّن أودو 17 رؤوس التخزين المؤقت للصور من /web/image.
أودو 18 و19لا توجد تغييرات كاسرة على عرض الصور. fields.Image و/web/image وt-field widget='image' تتصرف جميعها كما هو موثق. لا يزال wkhtmltopdf مطلوبًا لـ PDF.

تحتاج تقارير QWeb مخصصة أو قوالب بوابة لنظام أودو الخاص بك؟

يبني مطورونا المعتمدون في أودو تقارير PDF مخصصة وبوابات العملاء وقوالب المستندات ذات العلامة التجارية — بما في ذلك تصاميم PDF للفواتير الإلكترونية المتوافقة مع ZATCA وتصاميم التقارير العربية من اليمين لليسار للشركات السعودية.

واتساب

الأسئلة الشائعة

كيف أعرض صورة مخزنة في حقل نموذج أودو في قالب QWeb؟
استخدم وحدة التحكم `/web/image` مع `t-att-src` لقوالب الويب والبوابة: ``. لتقارير PDF، استخدم `t-field` بدلًا من ذلك: ``. لا تستخدم أبدًا رابط `/web/image` في تقارير PDF — لا يستطيع wkhtmltopdf جلب روابط HTTP من خادم أودو.
لماذا تظهر صورتي في المتصفح لكنها تظهر معطلة في تقرير PDF؟
السبب الأكثر شيوعًا هو استخدام `t-att-src` مع رابط `/web/image` في قالب تقرير PDF. يستطيع المتصفح جلب ذلك الرابط، لكن wkhtmltopdf (الذي يُنشئ PDF) يعمل كعملية منفصلة بدون وصول للشبكة إلى خادم أودو. الحل: استبدل `t-att-src` بـ `t-field` وأضف `t-options="{'widget': 'image'}"`. هذا يخبر أودو بتضمين الصورة كـ URI بيانات base64 مباشرةً في HTML قبل أن يعالجه wkhtmltopdf.
ما هو صيغة رابط /web/image في أودو؟
الصيغة الأساسية هي `/web/image///`. على سبيل المثال: `/web/image/res.partner/42/image_1920`. يمكنك إضافة لاحقة تغيير حجم اختيارية: `/web/image/res.partner/42/image_1920/128x128` — يُغيّر أودو حجم الصورة على جانب الخادم ويُخزّن النتيجة مؤقتًا. يحترم هذا الرابط التحكم في الوصول في أودو — سيتلقى المستخدمون الذين لا يملكون صلاحية قراءة السجل خطأ 404 أو صورة عنصر نائب اعتمادًا على تهيئة النموذج.
ما الفرق بين fields.Image وfields.Binary في أودو؟
`fields.Image` (أودو 13+) هو فئة فرعية متخصصة من `fields.Binary` مصممة للصور. يتحقق من الملف كتنسيق صورة معروف (PNG/JPEG/GIF/WebP/SVG)، ويمكنه تخزين نسخ متعددة بأحجام مختلفة تلقائيًا عند تعيين `max_width`/`max_height`، ويعمل مع ودجت الصورة في أودو في كلٍّ من عروض النموذج وQWeb. `fields.Binary` هو حقل ثنائي عام بدون التحقق من MIME أو تغيير الحجم التلقائي — مناسب للمستندات وجداول البيانات أو أي ملف عشوائي. كلاهما يُعرض بنفس الطريقة في QWeb: رابط `/web/image` أو `t-field widget='image'`.
كيف أعرض شعار الشركة في تقرير QWeb PDF لأودو؟
استخدم `t-field` على حقل `logo` للشركة: ``. إذا ورّثت من `web.external_layout` أو `web.basic_layout` القياسية، فإن شعار الشركة مدرج بالفعل في الرأس — لا تحتاج إلى إضافته يدويًا. إذا بنيت تخطيطًا مخصصًا من الصفر، استخدم نهج `t-field` أعلاه.
هل يمكنني تغيير حجم الصور باستخدام وحدة التحكم /web/image؟
نعم. أضف `/x` إلى الرابط: `/web/image/product.product/7/image_1920/200x200`. يُغيّر أودو حجم الصورة على جانب الخادم باستخدام PIL، يُخزّن النتيجة مؤقتًا، ويُعيد النسخة ذات الحجم المعدّل. إذا حددت العرض فقط (مثلًا `/200x0`) أو الارتفاع فقط (`/0x200`)، يقوم أودو بالقياس بشكل تناسبي. تغيير الحجم على جانب الخادم أكثر موثوقية من تغيير حجم CSS لأنه يُقلل البايتات الفعلية المنقولة — مفيد بشكل خاص لصور مصغرة المنتجات في عروض القوائم.
iWesabe Editorial Team

iWesabe Editorial Team

رؤى عملية حول Odoo ERP وامتثال ZATCA والعمليات الرقمية للشركات السعودية — بقلم فرق الاستشارات والمالية والهندسة في iWesabe.

عن iWesabe

مقالات ذات صلة