布局

在本章中,您将学习如何:

  • 创建自定义页眉。

  • 创建自定义页脚。

  • 修改标准模板。

  • 添加版权部分。

  • 提高网站的响应能力。

默认

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

继承ID

标准视图的ID(使用以下模式: 模块.模板

名称

修改后视图的易读名称

对于每个XPath,您需要修改两个属性: 表达式位置

Example

/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。

Position(位置)

位置定义了代码在模板中的放置位置。可能的值如下:

Position(位置)

描述

replace(替换)

使用XPath内容替换目标节点。

inside(内部)

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

before(之前)

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

after(之后)

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

attributes(属性)

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

Example

此 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 删除 header 的 class 属性中的 x_airproof_header。在这种情况下,您不需要使用 separator 属性。

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

此 XPath 在 header 的 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 指令时,强制您只能使用此类指令。

Example

Good example:
<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>
Bad example:
<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片段和页面。

参见

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网站构建器区分桌面模板和移动模板,以便根据设备调整用户体验。

桌面模板

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

重要

别忘了,您可能需要先禁用当前活动的页眉模板。

Example

/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': 'Contact',
   ),
);
/website_airproof/data/presets.xml
<record id="website.template_header_contact" model="ir.ui.view">
   <field name="active" eval="True"/>
</record>

移动模板

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

自定义

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

重要

别忘了,您可能需要先禁用当前活动的页眉模板。

选项

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

/website_airproof/views/website_templates.xml
<template id="template_footer_opt" inherit_id="website.snippet_options" name="Footer Template - Option">
   <xpath expr="//we-select[@data-variable='footer-template']" position="inside">
      <we-button title="airproof"
         data-customize-website-views="website_airproof.footer"
         data-customize-website-variable="'airproof'"  data-img="/website_airproof/static/src/img/wbuilder/template_footer_opt.svg"/>
   </xpath>
</template>

属性

描述

data-customize-website-views

要启用的模板

data-customize-website-variable

变量的名称

data-img

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

现在,您需要明确地定义要在Odoo SASS变量中使用您的自定义模板。

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

模板

/website_airproof/views/website_templates.xml
<record id="header" model="ir.ui.view">
   <field name="name">Airproof Header</field>
   <field name="type">qweb</field>
   <field name="key">website_airproof.header</field>
   <field name="inherit_id" ref="website.layout"/>
   <field name="mode">extension</field>
   <field name="arch" type="xml">
      <xpath expr="//header//nav" position="replace">
         <!-- Static Content -->
         <!-- Components -->
         <!-- Editable areas -->
      </xpath>
   </field>
</record>

别忘了相应地调整 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">
   <t t-set="_item_class" t-valuef="nav-item"/>
   <t t-set="_link_class" t-valuef="nav-link"/>
</t>

用户下拉菜单

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

语言选择器

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

行动号召

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

拖放区域

您可以不定义页面的完整布局,而是创建构建块(片段),让用户选择将它们拖放到何处,从而自行创建页面布局。我们称之为 模块化设计

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

<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 框架,该框架可增强网站在

桌面端和移动端的响应式能力。在 Odoo 16 中,您可以主要针对以下 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" name="Text">
    <!-- Content -->
</section>

在移动端隐藏一列:

<section class="s_text_block o_cc o_cc1 o_colored_level pt16 pb16" data-snippet="s_text_block" 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

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

重要

必须指定 o_snippet_mobile_invisible / o_snippet_desktop_invisible 类以保持

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

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