布局

在本章中,您将了解如何:

  • 创建自定义页眉。

  • 创建自定义页脚。

  • 修改标准模板。

  • 添加版权区域。

  • 改善网站的响应式效果。

默认

Odoo 页面由跨页元素和独有元素组成。跨页元素在每个页面上都相同,而独有元素仅与特定页面相关。默认情况下,一个页面有两个跨页元素,即页眉和页脚,以及一个包含该页面特定内容的独有主元素。

<div id="wrapwrap">
   <header/>
      <main>
         <div id="wrap" class="oe_structure">
            <!-- Page Content -->
         </div>
      </main>
   <footer/>
</div>

任何 Odoo XML 文件都以编码声明开头。之后,您必须在 <odoo> 标签内编写代码。

<?xml version="1.0" encoding="utf-8" ?>
<odoo>
   ...
</odoo>

注解

使用精确的模板名称对于快速在所有模块中查找信息非常重要。模板名称只能包含小写字母、数字和下划线。

请始终在文件末尾添加一个空行。通过配置 IDE 即可自动完成此操作。

XPath

XPath(XML 路径语言)是一种表达式语言,使您能够轻松遍历 XML 文档中的元素和属性。XPath 用于扩展标准的 Odoo 模板。

视图的编码方式如下。

<template id="..." inherit_id="..." name="...">
   <!-- Content -->
</template>

属性

说明

id

修改后视图的 ID

inherited_id

标准视图的 ID(使用以下模式:module.template)

name

修改后视图的人类可读名称

对于每个 XPath,您需要修改两个属性:expression 和 position。

示例

/website_airproof/views/website_templates.xml
<template id="layout" inherit_id="website.layout" name="Welcome Message">
   <xpath expr="//header" position="before">
      <!-- Content -->
   </xpath>
</template>

此 XPath 会在页面内容之前紧接着添加一条欢迎消息。

警告

替换默认元素的属性时请务必小心。由于您的主题继承自默认主题,您的更改将优先于今后任何 Odoo 更新。

注解

  • 每次创建新模板或记录时,您都应更新模块。

  • 继承视图的 XML ID 应与原始记录使用相同的 ID。这有助于一目了然地找到所有继承关系。由于最终的 XML ID 会以创建它们的模块作为前缀,因此不会出现重叠。

表达式

XPath 使用路径表达式在 XML 文档中选择节点。选择器在表达式中使用,用于定位正确的元素。下面列出了最常用的一些选择器。

后代选择器

说明

/

从根节点开始选择。

//

从当前节点开始,选择文档中与选择条件匹配的节点,无论它们位于何处。

属性选择器

说明

*

选择任何 XML 标签。如果需要更精确地选择,可以将 * 替换为特定的标签。

*[@id=”id”]

选择特定的 ID。

*[hasclass(“class”)] 选择器

选择特定的类。

*[@name=”name”] 选择器

选择具有特定名称的标签。

*[@t-call=”t-call”] 选择器

选择特定的 t-call。

位置

位置决定代码在模板中的放置位置。可能的值如下所示:

位置

说明

replace

用 XPath 内容替换目标节点。

inside

将 XPath 内容添加到目标节点内部。

before

将 XPath 内容添加到目标节点之前。

after

将 XPath 内容添加到目标节点之后。

attributes

将 XPath 内容添加到属性内部。

示例

此 XPath 会移除第一个具有 .breadcrumb 类的元素。

<xpath expr="//*[hasclass('breadcrumb')]" position="replace"/>

此 XPath 会在 <ul> 元素的最后一个子元素之后添加一个额外的 <li> 元素。

<xpath expr="//ul" position="inside">
   <li>Last element of the list</li>
</xpath>

此 XPath 会在作为 <header> 直接子元素的 <nav> 之前添加一个 <div>。

<xpath expr="//header/nav" position="before">
   <div>Some content before the header</div>
</xpath>

此 XPath 会移除页眉 class 属性中的 x_airproof_header。在这种情况下,您无需使用 separator 属性。

<xpath expr="//header" position="attributes">
   <attribute name="class" remove="x_airproof_header" />
</xpath>

此 XPath 会在页眉的 class 属性中添加 x_airproof_header。您还需要定义 separator 属性,以便在要添加的类之前添加一个空格。

<xpath expr="//header" position="attributes">
   <attribute name="class" add="x_airproof_header" separator=" " />
</xpath>
此 XPath 会将具有 .o_footer_scrolltop_wrapper 类的元素移动到具有

footer ID 属性的元素之前。

<xpath expr="//div[@id='footer']" position="before">
   <xpath expr="//div[@id='o_footer_scrolltop_wrapper']" position="move" />
</xpath>

小技巧

在其他 XPath 内使用 move 指令会强制您只能使用这种指令。

示例

良好示例:
<xpath expr="//*[hasclass('o_wsale_products_main_row')]" position="before">
   <xpath expr="//t[@t-if='opt_wsale_categories_top']" position="move" />
</xpath>
<xpath expr="//*[hasclass('o_wsale_products_main_row')]" position="before">
   <div><!-- Content --></div>
</xpath>
错误示例:
<xpath expr="//*[hasclass('o_wsale_products_main_row')]" position="before">
   <xpath expr="//t[@t-if='opt_wsale_categories_top']" position="move" />
   <div><!-- Content --></div>
</xpath>

更多内容

您可以在此 速查表 中找到有关 XPath 的更多信息。

QWeb

QWeb 是 Odoo 使用的主要模板引擎。它是一种 XML 模板引擎,主要用于生成 HTML 片段和页面。

t-call 指令可以接收参数:

<!-- Old way -->
<t t-call="portal.user_dropdown">
   <t t-set="_icon" t-value="True" />
   <t t-set="_item_class" t-valuef="dropdown" />
</t>

<t t-call="website.layout">
   <t t-set="additional_title">My page title</t>
</t>

<!-- New way (Parametric) -->
<t t-call="portal.user_dropdown"
   _icon="true"
   _item_class.f="dropdown" />

<t t-call="website.layout"
   additional_title.translate="My page title" />

属性(示例)

说明

_icon="true"

传递原始值(此处为设为 true 的布尔值)

_item_class.f="dropdown"

以字符串形式传递值

additional_title.translate="My page title"

以字符串形式传递值

更多内容

QWeb 模板文档。

自定义字段

根据您的需求,您可以创建自定义字段,以便将数据保存在数据库中。

声明

首先,创建一条记录来声明该字段。该字段必须关联到一个现有的模型。

/website_airproof/data/fields.xml
<record id="x_post_category" model="ir.model.fields">
   <field name="name">x_post_category</field>
   <field name="field_description">...</field>
   <field name="ttype">html</field>
   <field name="state">manual</field>
   <field name="index">0</field>
   <field name="model_id" ref="website_blog.model_blog_post" />
</record>

注解

也可以通过 使用 Python 定义模型 来创建字段(推荐这样做)。

后端

通过 XPath 将字段添加到相关视图中。这样,用户就能在界面中看到该字段并在之后填写它。

/website_airproof/views/backend/website_blog_views.xml
<record id="view_blog_post_form_category" model="ir.ui.view">
   <field name="name">view_blog_post_form_category</field>
   <field name="model">blog.post</field>
   <field name="inherit_id" ref="website_blog.view_blog_post_form" />
   <field name="arch" type="xml">
      <xpath expr="//field[@name='blog_id']" position="before">
         <field name="x_post_category" string="..." placeholder="..." />
      </xpath>
   </field>
</record>

前端

通过调用 model_name.field_name,可以在页面的某个位置显示该字段的值,如下所示:

/website_airproof/views/website_blog_templates.xml
<h1 t-field="blog_post.x_post_category" />

背景

您可以将颜色或图像定义为网站的背景。

颜色

/website_airproof/static/src/scss/primary_variables.scss
$o-color-palettes: map-merge($o-color-palettes,
   (
      'airproof': (
         'o-cc1-bg':                     'o-color-5',
         'o-cc5-bg':                     'o-color-1',
      ),
    )
);

图像/图案

/website_airproof/static/src/scss/primary_variables.scss
$o-website-values-palettes: (
   (
      'body-image': '/website_airproof/static/src/img/background-lines.svg',
      'body-image-type': 'image' or 'pattern'
   )
);

标准

Odoo 网站构建器区分桌面端模板和移动端模板,以便根据设备调整用户体验。

桌面端模板

启用其中一个默认页眉模板。

重要

请不要忘记,您可能需要先禁用当前已启用的页眉模板。

示例

/website_aiproof/data/presets.xml
<record id="website.template_header_default" model="ir.ui.view">
   <field name="active" eval="False" />
</record>

在 primary_variables.scss 文件中显式设置所需的模板。

/website_airproof/static/src/scss/primary_variables.scss
$o-website-values-palettes: (
   (
      'header-template': 'stretch',
   ),
);
/website_airproof/data/presets.xml
<record id="website.template_header_stretch" model="ir.ui.view">
   <field name="active" eval="True" />
</record>

移动端模板

每个页眉模板都附带 template_header_mobile 模板,以确保在所有设备上提供无缝的用户体验。

自定义

创建您自己的模板并将其添加到列表中。

重要

请注意,在启用自定义页头模板之前,可能需要先禁用当前启用的页头模板。

选项

使用以下代码在网站构建器中为新的自定义页眉添加选项。

/website_airproof/static/src/website_builder/header_template_option.xml
<t t-name="website_airproof.HeaderTemplateOption" t-inherit="website.HeaderTemplateOption" t-inherit-mode="extension">
   <xpath expr="//BuilderRow[@label.translate='Template']//BuilderSelect" position="inside">
      <BuilderSelectItem
         id="'header_airproof_opt'"
         title.translate="Airproof"
         actionParam="[
            {
               action: 'websiteConfig',
               actionParam: {
                  views: ['website_airproof.header'],
                  vars: { 'header-template': 'airproof' },
                  checkVars: false,
               },
            },
         ]">
         <Img src="'/website_airproof/static/src/img/wbuilder/template-header-opt.svg'" attrs="{ style: 'width: calc(100% - 0.5rem);' }" />
      </BuilderSelectItem>
   </xpath>
 </t>

属性

说明

views

要启用的模板

vars

赋予该变量的名称(与 primary_variables.scss 中使用的名称相同)

checkVars

确定是否比较 vars 以设置选项状态。

src(位于 Img 中)

在网站构建器的模板选择中显示的自定义模板缩略图

现在将此文件添加到 __manifest__.py 的 website.website_builder_assets 资源包中,并在 Odoo SASS 变量中将自定义模板显式定义为页头模板。

/website_airproof/static/src/scss/primary_variables.scss
$o-website-values-palettes: (
   (
      'header-template': 'airproof',
   ),
);

模板

/website_airproof/views/website_templates.xml
<template id="header" inherit_id="website.layout" name="Airproof - Header" active="True">
   <xpath expr="//header//nav" position="replace">
      <!-- Static Content -->
      <!-- Components -->
      <!-- Editable areas -->
   </xpath>
</template>

请不要忘记相应地调整 template_header_mobile,以保持桌面端和移动端的一致性:

website_airproof/views/website_templates.xml
<template id="template_header_mobile" inherit_id="website.template_header_mobile" name="Airproof - Template Header Mobile">
   <!-- Xpaths -->
</template>

组件

在自定义页眉中,您可以使用 QWeb 的 t-call 指令调用多个子模板:

登录

<t t-call="portal.placeholder_user_sign_in"
   _item_class.f="nav-item"
   _link_class.f="nav-link" />

用户下拉菜单

<t t-call="portal.user_dropdown"
   _user_name="true"
   _icon="false"
   _avatar="false"
   _item_class.f="nav-item dropdown"
   _link_class.f="nav-link"
   _dropdown_menu_class.f="..." />

语言选择器

<t t-call="website.placeholder_header_language_selector"
   _div_classes.f="..." />

行动号召

<t t-call="website.placeholder_header_call_to_action"
   _div_classes.f="..." />

拖放区域

您可以创建构建块(代码片段),让用户自行选择拖放位置,从而自行创建页面布局,而不必定义页面的完整布局。我们称之为 模块化设计。

您可以定义一个空白区域,供用户用代码片段填充。

<div id="oe_structure_layout_01" class="oe_structure" />

类

说明

oe_structure

为用户定义一个拖放区域。

oe_structure_solo 类

此区域只能放置一个代码片段。

oe_structure_not_nearest 类

如果构建块被放置到具有此类的拖放区域之外,该块将被移动到最近的拖放区域中。

您也可以用您的内容填充现有的拖放区域。

<template id="oe_structure_layout_01" inherit_id="..." name="...">
   <xpath expr="//*[@id='oe_structure_layout_01']" position="replace">
      <div id="oe_structure_layout_01" class="oe_structure oe_structure_solo">
         <!-- Content -->
      </div>
   </xpath>
</template>

响应式

Odoo 总体上依赖 Bootstrap 框架,它使你的网站在桌面端和移动端更易于实现响应式。你主要可以从 3 个方面入手:

  1. 根据设备自动计算字号

  2. 桌面端的列宽(在移动端,各列会自动堆叠)

  3. 可见性条件(在桌面端/移动端显示/隐藏某些内容)

字号

在 Bootstrap 5 中,响应式字号默认启用,使文本能够更自然地在不同设备和视口尺寸之间缩放(依赖于 $enable-rfs 变量)。

列宽

Bootstrap 使用由行和列组成的网格来布局页面。得益于这种结构,列在移动端和桌面端可以设置不同的宽度。在此版本中,网站构建器允许设置移动端尺寸 col-12 和桌面端尺寸 col-lg-4,但无法设置中等断点 col-md-4。

警告

中等尺寸可以设置,但最终用户无法在网站构建器中编辑它们。

可见性条件

在 Odoo 网站构建器中,可以将整个区域或特定的列在移动端或桌面端隐藏。

此功能结合使用 Bootstrap 和 Odoo 专属的类:

  • o_snippet_mobile_invisible

  • o_snippet_desktop_invisible

在桌面端隐藏区域:

<section
   class="s_text_block o_cc o_cc1 o_colored_level pt16 pb16 d-lg-none o_snippet_desktop_invisible"
   data-snippet="s_text_block"
   data-name="Text">
   <!-- Content -->
</section>

在移动端隐藏列:

<section
   class="s_text_block o_cc o_cc1 o_colored_level pt16 pb16"
   data-snippet="s_text_block"
   data-name="Text">
   <div class="container s_allow_columns">
      <div class="row">
         <div class="col-12 col-lg-6 d-none d-lg-block o_snippet_mobile_invisible">
            Column 1
         </div>
         <div class="col-12 col-lg-6">
            Column 2
         </div>
      </div>
   </div>
</section>

类

说明

o_snippet_mobile_invisible 类

它告知网站构建器:该元素已隐藏,并且使用了可见性条件选项。

o_snippet_desktop_invisible 类

它告知网站构建器:该元素 在桌面端 已隐藏,并且使用了可见性条件选项。

d-none

在所有情况下隐藏该元素。

d-lg-block

从“large”断点(桌面端)开始显示该元素。

重要

必须指定 o_snippet_mobile_invisible / o_snippet_desktop_invisible 类,以保持

可见性条件选项正常工作。即使某个元素在桌面端被隐藏,网站构建器也会显示这些元素的列表,让最终用户能够强制显示该元素并进行编辑,而无需在移动端和桌面端模式之间切换。

在当前设备上强制显示隐藏的元素。