Bỏ qua để đến nội dung

Jinja placeholders — Cheatsheet

Cheatsheet reference cho pháp chế / Admin tạo template .docx với Jinja placeholders.

{{ record.customer_id.name }}
{{ record.total_amount }}
{{ company.name }}
{% if record.state == 'active' %}
HĐ đang hiệu lực
{% else %}
HĐ chưa active
{% endif %}
{% for line in record.billing_item_ids %}
{{ loop.index }}. {{ line.name }}{{ line.amount }} VND
{% endfor %}
{{ record.amount_total | round(0) }} # Làm tròn
{{ record.date_start | date_format }} # Format DD/MM/YYYY
{{ record.name | upper }} # In hoa

Wizard truyền context với các keys sau:

KeyModelVí dụ dùng
recordRecord đang renderrecord.name, record.customer_id
companyenv.company hoặc record.company_idcompany.name, company.vat
userUser đang renderuser.name
todayDate hôm nay{{ today | date_format }}
today_fullDate full VN”Ngày 15 tháng 8 năm 2026”
{{ record.name }} # ZC-2026-042
{{ record.date_start | date_format }} # 01/08/2026
{{ record.date_end | date_format }} # 31/07/2076
{{ record.duration_months }} # 600
{{ record.total_amount }} # 150,000,000,000
{{ record.currency_id.name }} # VND
{{ record.name }} # S-2026-042
{{ record.date_order | date_format }}
{{ record.validity_date | date_format }}
{{ record.amount_untaxed }}
{{ record.amount_tax }}
{{ record.amount_total }}
{{ record.partner_id.name }} # KH
{% for line in record.order_line %}
{{ line.product_id.name }}{{ line.product_uom_qty }} × {{ line.price_unit }} = {{ line.price_subtotal }}
{% endfor %}
{{ record.name }} # DA-2026-018
{{ record.partner_id.name }}
{{ record.deposit_amount }}
{{ record.deposit_paid_amount }}
{{ record.date_signed | date_format }}
{{ record.date_paid_in_full | date_format }}
{% for tranche in record.deposit_tranche_ids %}
Đợt {{ loop.index }}: {{ tranche.date_planned | date_format }} - {{ tranche.amount }} VND
{% endfor %}
Customer refund policy: {{ record.customer_refund_policy_label }}
Developer refund policy: {{ record.developer_refund_policy_label }}
{{ record.date_start | date_format }} # 15/08/2026
{{ record.date_start | date_format('%d/%m/%Y') }} # 15/08/2026 (default)
{{ record.date_start | date_format('%B %d, %Y') }} # August 15, 2026
{{ record.date_start | date_format_vn_long }} # "Ngày 15 tháng 8 năm 2026"
{{ record.total_amount | currency_format }} # "150,000,000,000 ₫"
{{ record.total_amount | currency_format('USD') }} # "6,000,000 $"
{{ 1234567 | number_format }} # "1,234,567"
{{ 1234.5678 | number_format(2) }} # "1,234.57"
{{ record.customer_id.name | upper }} # In HOA
{{ record.customer_id.name | lower }} # in thường
{{ record.customer_id.name | title }} # Title Case
{{ text | truncate(50) }} # Cắt 50 chars
{{ record.x_fax or '(không có)' }} # Fallback
{{ record.customer_id.name | default('Khách vô danh') }}
{% set weekday = record.date_start.weekday() %}
{% set days = ['Thứ Hai','Thứ Ba','Thứ Tư','Thứ Năm','Thứ Sáu','Thứ Bảy','Chủ Nhật'] %}
{{ days[weekday] }}, ngày {{ record.date_start.day }} tháng {{ record.date_start.month }} năm {{ record.date_start.year }}

Output: “Thứ Tư, ngày 15 tháng 8 năm 2026”

Cần custom filter to_vietnamese_words (Admin add):

{{ record.total_amount }} đồng ({{ record.total_amount | to_vietnamese_words }})

Output: “150,000,000,000 đồng (Một trăm năm mươi tỷ đồng)“

{% if record.customer_id.x_company_type == 'fdi' %}
<p>Số IRC: {{ record.customer_id.x_irc_number }}</p>
<p>Vốn đầu tư: {{ record.customer_id.x_investment_capital }} USD</p>
{% else %}
<p>Số ĐKKD: {{ record.customer_id.company_registry }}</p>
{% endif %}
{% for milestone in record.milestone_ids %}
Mốc {{ loop.index }}: {{ milestone.name }}
{% for payment in milestone.payment_ids %}
- Thanh toán {{ payment.date | date_format }}: {{ payment.amount }} VND
{% endfor %}
{% endfor %}
  • Placeholder không được replace → syntax sai (thiếu quote, thừa space, misspell field)
  • Verify field tồn tại: mở record → xem field trong Odoo backend
  • Field không tồn tại trên model → check spell
  • Field trên related model → thiếu . chain (vd record.customer_id không có .name)
  • Field is False / null → dùng or fallback: {{ value or 'N/A' }}
  • Related Many2one is empty → check parent first: {% if record.customer_id %}{{ record.customer_id.name }}{% endif %}
  • Filter chưa install trong docxtpl → dùng Python built-in: {{ "%.2f" | format(record.amount) }}

Odoo Selection field lưu key English (vd 'active'). Muốn label VN, dùng _label suffix (Parkone custom):

{{ record.state_label }} # "Đang hoạt động" (not 'active')
{{ record.customer_id.x_company_type_label }} # "Nước ngoài (FDI)"
{{ record.lot_id.lot_type_label }} # "Đất công nghiệp"

Nếu template dùng .state direct → render “active” (English) → không professional.

Copy vào Word template comment block:

=== JINJA CHEATSHEET ===
{{ var }} Print
{% if x %}...{% endif %} Condition
{% for x in list %}...{% endfor %} Loop
{{ x | filter }} Apply filter
Contract fields:
- record.name / date_start / total_amount / duration_months
- record.customer_id.name / vat / x_legal_representative
- record.project_id.investor_id.name / vat / bank_acc_vnd_id.acc_number
Filters:
- | date_format → 15/08/2026
- | currency_format → "1,000,000 ₫"
- | number_format(2) → "1,234.57"
- | upper / lower / title
- | truncate(50)
- | default('N/A')
Vietnamese:
- | to_vietnamese_words → "Một triệu đồng"
- date_format_vn_long → "Ngày 15 tháng 8 năm 2026"
Chia sẻ: