草庐IT

odoo 开发入门教程系列-一些用户界面

授客的博客 2023-03-28 原文

一些用户界面

数据文件 (XML)

参考: 该主题关联文档可以查看Data Files.

上一章,我们通过CSV文件添加了数据。当需要添加数据格式简单时,用CSV格式还是很方便的,当数据格式更复杂时(比如视图架构或者一个邮件模板),我们使用XML格式。比如包含HTML tags的 help field。虽然可以通过CSV文件加载这样的数据,但是使用XML更方便。

类似CSV文件,XML文件也必须按约定添加到合适的目录,并在 __manifest__.py中进行定义。数据文件中的内容也是在模块安装或者更新时按序加载。因此,对CSV文件所做的所有说明对XML文件都适用。当数据链接到视图时,我们将它们添加到views文件夹中

本章,我们将通过XML文件加载我们第一个action和菜单。Actions 和菜单为数据库中的标准记录。

注解:

当程序很注重性能时,CSV格式优先于XML格式。这是因为,在odoo中加载CSV文件比加载XML文件更快。

odoo中,用户接口(action,菜单和视图)大部分是通过创建和组装XML文件中的记录来定义的。常见的模式为 菜单> action > 视图。为了访问记录,用户在几个菜单级中导航。最深层是触发打开记录列表的action。

操作(Actions)

参考: 主题相关文档可以查看 Actions.

动作可以通过三种方式触发 :

  1. 点击菜单项目(链接接到指定动作)
  2. 点击视图按钮(如果与action关联)
  3. 对象的上下文action

本章仅涵盖第一种情况。 我们Real Estate例子中,希望将一个菜单连接到 estate.property model, 以便创建一个新记录。 action可以视为菜单和model之间的链接

test.model 的基本action:

<record id="test_model_action" model="ir.actions.act_window">
    <field name="name">Test action</field>
    <field name="res_model">test.model</field>
    <field name="view_mode">tree,form</field>
</record>
  • id 外部标识。它可以用于引用记录(不需要知道其在数据库中的标识符)。
  • model ir.actions.act_window (Window Actions (ir.actions.act_window))的一个固定值
  • name action名称
  • res_model action应用的范围。
  • view_mode 可获取的视图。本例中为列表(树)和表格视图。

odoo中到处都可以找到例子,但是这个 简单action的好例子。关注XML 数据文件结构,因为你在后续的练习中会用到。

<?xml version="1.0"?>
<odoo>
    <record id="crm_lost_reason_view_search" model="ir.ui.view">
        <field name="name">crm.lost.reason.view.search</field>
        <field name="model">crm.lost.reason</field>
        <field name="arch" type="xml">
            <search string="Search Opportunities">
                <field name="name"/>
                <filter string="Include archived" name="archived" domain="['|', ('active', '=', True), ('active', '=', False)]"/>
                <separator/>
                <filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
            </search>
        </field>
    </record>

    <record id="crm_lost_reason_view_form" model="ir.ui.view">
        <field name="name">crm.lost.reason.form</field>
        <field name="model">crm.lost.reason</field>
        <field name="arch" type="xml">
            <form string="Lost Reason">
                <sheet>
                    <div class="oe_button_box" name="button_box">
                        <button name="action_lost_leads" type="object"
                            class="oe_stat_button" icon="fa-star">
                            <div class="o_stat_info">
                                <field name="leads_count" class="o_stat_value"/>
                                <span class="o_stat_text"> Leads</span>
                            </div>
                        </button>
                    </div>
                    <widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
                    <div class="oe_title">
                        <div class="oe_edit_only">
                            <label for="name"/>
                        </div>
                        <h1 class="mb32">
                            <field name="name" class="mb16"/>
                        </h1>
                        <field name="active" invisible="1"/>
                    </div>
                </sheet>
            </form>
        </field>
    </record>

    <record id="crm_lost_reason_view_tree" model="ir.ui.view">
        <field name="name">crm.lost.reason.tree</field>
        <field name="model">crm.lost.reason</field>
        <field name="arch" type="xml">
            <tree string="Channel" editable="bottom">
                <field name="name"/>
            </tree>
        </field>
    </record>

    <!-- Configuration/Lead & Opportunities/Lost Reasons Menu -->
    <record id="crm_lost_reason_action" model="ir.actions.act_window">
        <field name="name">Lost Reasons</field>
        <field name="res_model">crm.lost.reason</field>
        <field name="view_mode">tree,form</field>
        <field name="help" type="html">
          <p class="o_view_nocontent_smiling_face">
            Define a new lost reason
          </p><p>
            Use lost reasons to explain why an opportunity is lost.
          </p><p>
            Some examples of lost reasons: "We don't have people/skill", "Price too high"
          </p>
        </field>
    </record>

    <record id="menu_crm_lost_reason" model="ir.ui.menu">
        <field name="action" ref="crm.crm_lost_reason_action"/>
    </record>
</odoo>

练习

estate.property model 创建action。

在适当的位置(本例中为odoo14/custom/estate/models/views)创建 estate_property_views.xml

<?xml version="1.0"?>
<odoo>
    <record id="link_estate_property_action" model="ir.actions.act_window">
        <field name="name">Properties</field>
        <field name="res_model">estate.property</field>
        <field name="view_mode">tree,form</field>
    </record>
</odoo>

修改odoo14/custom/estate/__manifest__.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
    'name': 'estate',
    'depends': ['base'],
    'data':['security/ir.model.access.csv',
            'views/estate_property_views.xml'
            ]
}

重启服务并观察文件加载日志。

菜单(Menus)

参考: 和本主题关联文档可以查看Shortcuts.

为了减少菜单(ir.ui.menu)定义和链接到对应action的复杂性,我们可以使用 shortcut

test_model_action 一个的基础菜单:

<menuitem id="test_model_menu_action" action="test_model_action"/>

test_model_menu_action 菜单被链接到 test_model_actionaction链接到model test.model。正如前面所述, action可以看做是菜单和model之间的连接。

注意:这里的id的值和action的值不能设置成一样,否则会报错。

然而,菜单总是遵循一种体系结构,实际上有三个层次的菜单:

  1. 根菜单,显示在App切换器中(Odoo社区版切换器是一个下拉菜单)
  2. 第一级菜单,显示在顶部栏中
  3. 动作菜单

最容易的方式是在XML文件中定义结构来创建菜单。

test_model_action 定义的一个基础菜单结构:

<menuitem id="test_menu_root" name="Test">
    <menuitem id="test_first_level_menu" name="First Level">
        <menuitem id="test_model_menu_action" action="test_model_action"/>
    </menuitem>
</menuitem>

第三级菜单的名称,直接从action获取,即为action属性值

练习

添加菜单

在合适的目录(本例中为odoo14/custom/estate/models/views)创建 estate_menus.xml 文件

<?xml version="1.0"?>
<odoo>
    <menuitem id="test_menu_root" name="Test">
        <menuitem id="test_first_level_menu" name="First Level">
            <menuitem id="estate_property_menu_action" action="link_estate_property_action"/>
        </menuitem>
    </menuitem>
</odoo>

修改odoo14/custom/estate/__manifest__.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
    'name': 'estate',
    'depends': ['base'],
    'data':['security/ir.model.access.csv',
            'views/estate_property_views.xml',
            'views/estate_menus.xml'
            ]
}

重启odoo服务,查看效果

字段,属性和视图(Fields, Attributes And View)

到目前为止,我们只对房产广告使用了通用视图,但在大多数情况下,我们希望对视图进行微调。Odoo有许多微调方式,但通常第一步是确保:

  • 某些字段有默认值
  • 某些字段只读
  • 当记录重复时,某些字段不能被拷贝

在我们的房产业务案例中,我们希望::

  • 售价只读(往后将自动填充)
  • 当记录重复时,可用日期和售价不能被拷贝
  • 卧室数量应该默认为2
  • 默认可用日期应该为3个月

一些新属性

在进一步进行视图设计之前,让我们回到模型定义。我们看到一些属性,如required=True,会影响数据库中的表模式。其他属性也将影响视图或提供默认值。

练习 -- 添加一些属性到字段。

查找一些合适的属性 (查看字段) 来:

  • 设置售价为只读
  • 阻止复制可用日期和售价

修改 odoo14\custom\estate\models\estate_property.pyEstateProperty类属性expected_priceselling_price的值如下:

expected_price = fields.Float('expected price', digits=(8, 2),  required=True) 
selling_price = fields.Float('selling price', digits=(8, 2), readonly=True, copy=False)

重启服务和并刷新浏览器界面,我们可以看到无法设置任何售价。复制记录时,可用日期应为空。

预期效果可参考该动画连接:https://www.odoo.com/documentation/14.0/zh_CN/_images/attribute_and_default.gif

默认值

可以为任何字段设置默认值。字段定义中,添加 default=X, 其中的X 可以是Python文本值(boolean, integer, float, string) ,也可以是一个以model对象自身为入参并返回一个值的函数:

name = fields.Char(default="Unknown")
last_seen = fields.Datetime("Last Seen", default=lambda self: fields.Datetime.now())

例中name字段默认值为‘Unknown’,而last_seen 字段默认值为当前时间

练习 -- 设置默认值

添加适当的默认值:

  • 卧室数量默认值为 2
  • 可用日期默认为3个月内

修改 odoo14\custom\estate\models\estate_property.pyEstateProperty类属性bedroomsselling_price的值如下:

bedrooms = fields.Integer(default=2)
date_availability = fields.Datetime('Availability Date', copy=False, default= lambda self: fields.Datetime.today())

重启服务和并刷新浏览器界面验证

保留字段

参考: 主题相关文档可参考 保留字段名称.

odoo为预定义行为保留了一些字段名称。当需要相关行为时,需要在模型中定义这些保留字段。

练习 -- 添加active字段

添加一个 active 字段到estate.property 模型。

修改 odoo14\custom\estate\models\estate_property.pyEstateProperty类,增加active属性

active = fields.Boolean('Active')

重启服务,刷新浏览器界面,新增一条记录,新增时勾选Active复选框,即active=True,验证效果。

预期效果可参考该动画链接:https://www.odoo.com/documentation/14.0/zh_CN/_images/inactive.gif

注意,已存在的记录的active字段默认值为False

练习--为active字段添加设置

active字段设置默认值

active 字段设置适当的属性值,让它不再出现在页面。

练习 -- 添加state字段

estate.property model添加state 字段(字段名可自定义),一个选择列表。可选值: New, Offer Received, Offer Accepted, SoldCanceled。必选字段,且不能被拷贝,默认值New

修改 odoo14\custom\estate\models\estate_property.pyEstateProperty类,修改active字段,增加state字段

    active = fields.Boolean('Active', default=True, invisible=True) # 注意:实践发现,invisible字段不起作用
    state = fields.Selection(
        string='State',
        selection=[('New','New'),
                   ('Offer Received','Offer Received'),
                   ('Offer Accepted', 'Offer Accepted'),
                   ('Sold','Sold'),
                   ('Canceled', 'Canceled')],
        copy=False
    )

重启服务,验证效果

有关odoo 开发入门教程系列-一些用户界面的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  3. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  6. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  7. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  8. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  9. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  10. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

    我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

随机推荐