Odoo10开发教程八(向导与国际化)

向导

向导以动态形式描述与用户(或对话框)的交互式会话。向导与其他的模型不同,其基类是TransientModel而不是常见的ModelTransientModel类扩展自Model,并使用了其所有机制,具有以下特殊性:

  • 向导记录不是永久性的,会在一段时间后自动从数据库中删除。这就是为什么他们被称为瞬态
  • 向导模型不需要访问权限:用户拥有向导记录的所有权限
  • 向导记录可以通过many2one字段引用普通记录或向导记录,但普通记录无法通过many2one引用向导记录。
    我们要创建一个向导,用来让用户可以生成授课的参与者,或者一次创建一个授课列表。

练习定义向导
创建一个向导模型,这个向导模型通过many2one关联授课模型,并通过many2many关联合作伙伴模型。添加新文件openacademy/wizard.py

openacademy/__init__.py

from . import controllers
from . import models
from . import partner
from . import wizard

openacademy/wizard.py

# -*- coding: utf-8 -*-

from odoo import models, fields, api

class Wizard(models.TransientModel):
    _name = 'openacademy.wizard'

    session_id = fields.Many2one('openacademy.session',
        string="Session", required=True)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")
启动向导

向导通过ir.actions.act_window记录来启动,target字段设置值为new。后者将在一个弹出窗口中打开向导。操作可以有菜单项触发。还有另外一种方式来启动向导:使用类似于上面的ir.actions.act_window记录,但有一个额外字段src_model,指定那个模型的操作可用。该向导将出现在模型主视图的上下文操作中。因为这是在ORM中的内部钩子,所以这个操作通过在XML文件的act_window标签中进行定义。


向导使用常规视图并且它的按钮可以使用special="cancel"来关闭向导窗口而不需要保持。

练习启动向导

  1. 为向导定义一个form视图
  2. 在授课模型的上下文中添加action用于启动向导
  3. 给向导的session字段定义默认值;使用上下文参数self._context来获取当前授课

openacademy/wizard.py

class Wizard(models.TransientModel):
    _name = 'openacademy.wizard'

    def _default_session(self):
        return self.env['openacademy.session'].browse(self._context.get('active_id'))

    session_id = fields.Many2one('openacademy.session',
        string="Session", required=True, default=_default_session)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

openacademy/views/openacademy.xml

                  parent="openacademy_menu"
                  action="session_list_action"/>

        
            wizard.form
            openacademy.wizard
            
                

练习注册与会者
给向导添加按钮,并且实现相应的方法,将与会者添加到给定的授课。

openacademy / views / openacademy.xml

                        
                    
                    

openacademy/wizard.py

    session_id = fields.Many2one('openacademy.session',
        string="Session", required=True, default=_default_session)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

    @api.multi
    def subscribe(self):
        self.session_id.attendee_ids |= self.attendee_ids
        return {}

练习与会者注册多个授课
修改向导模型,以便与会者可以注册到多个授课

openacademy/views/openacademy.xml

                

openacademy/wizard.py

class Wizard(models.TransientModel):
    _name = 'openacademy.wizard'

    def _default_sessions(self):
        return self.env['openacademy.session'].browse(self._context.get('active_ids'))

    session_ids = fields.Many2many('openacademy.session',
        string="Sessions", required=True, default=_default_sessions)
    attendee_ids = fields.Many2many('res.partner', string="Attendees")

    @api.multi
    def subscribe(self):
        for session in self.session_ids:
            session.attendee_ids |= self.attendee_ids
        return {}

国际化

每个模块都可以在i18n目录提供自己的翻译,文件名的形式为LANG.po,其中LANG是语言的代码,或者是语言和国家的组合,例如:pt.po(葡萄牙语)和pt_BR.po(巴西葡萄牙语)。对于所有开启的语言,Odoo都会自动载入翻译。开发者总是使用英语建立模块,然后使用Odoo的文本POT导出功能导出模块术语(设置->翻译->导入/导出->导出翻译),生成模块的POT模板文件,然后到处PO翻译文件。许多IDE具有用于编辑和合并PO/POT文件的插件或功能。

提示
把Odoo生成的导出文件公布在Transifex,可以轻松的使用软件进行翻译。

|- idea/ # The module directory
   |- i18n/ # Translation files
      | - idea.pot # Translation Template (exported from Odoo)
      | - fr.po # French translation
      | - pt_BR.po # Brazilian Portuguese translation
      | (...)

提示
默认情况下Odoo的POT导出仅提取XML文件的标签和Python代码中的字段定义,但是任何Python字符串都可以翻译,通过使用odoo._()方法,例如_("Label")


练习
翻译一个模块
为已经安装的Odoo模块选择第二语言。使用Odoo提供的功能对模块进行翻译。

  1. 创建目录openacademy/i18n/
  2. 安装任意一种你希望的语言 (设置->翻译->加载翻译
  3. 同步翻译术语(设置->翻译->应用程序术语->同步术语
  4. 导出不指定语言的翻译模板文件(设置->翻译->导入/导出->导出翻译),保存在openacademy/i18n/
  5. 导出指定语言的翻译文件(设置->翻译->导入/导出->导出翻译),保存在openacademy/i18n/
  6. 打开导出的翻译文件(使用任意一款文本编辑软件或者专用的PO文件编辑器,例如POEdit然后翻译其中的术语)
  7. models.py文件中,为odoo._方法添加一个导入声明,并且标记需要翻译的字符串
  8. 重复3-6的步骤

openacademy/models.py

# -*- coding: utf-8 -*-

from datetime import timedelta
from odoo import models, fields, api, exceptions, _

class Course(models.Model):
    _name = 'openacademy.course'
        default = dict(default or {})

        copied_count = self.search_count(
            [('name', '=like', _(u"Copy of {}%").format(self.name))])
        if not copied_count:
            new_name = _(u"Copy of {}").format(self.name)
        else:
            new_name = _(u"Copy of {} ({})").format(self.name, copied_count)

        default['name'] = new_name
        return super(Course, self).copy(default)
        if self.seats < 0:
            return {
                'warning': {
                    'title': _("Incorrect 'seats' value"),
                    'message': _("The number of available seats may not be negative"),
                },
            }
        if self.seats < len(self.attendee_ids):
            return {
                'warning': {
                    'title': _("Too many attendees"),
                    'message': _("Increase seats or remove excess attendees"),
                },
            }
    def _check_instructor_not_in_attendees(self):
        for r in self:
            if r.instructor_id and r.instructor_id in r.attendee_ids:
                raise exceptions.ValidationError(_("A session's instructor can't be an attendee"))

你可能感兴趣的:(Odoo10开发教程八(向导与国际化))