Skip to content
  • Categories
  • Tags
  • Popular
  • Users
  • Groups
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (Flatly)
  • No Skin
Collapse

Odoo 中文社区

  1. Home
  2. Categories
  3. Odoo 培训
  4. 至死都被误解的ODOO的API

至死都被误解的ODOO的API

Scheduled Pinned Locked Moved Odoo 培训
api.oneapi.multiapi.model
1 Posts 1 Posters 1.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    digitalsatori
    管理员
    wrote on last edited by digitalsatori
    #1

    api.one api.multi 已淘汰

    首先需要澄清,随着当前最新的Odoo版本V13.0发布以后。 api.one 和 api.multi 作为Odoo的实体类方法的装饰器的用法已经淘汰。在V13.0以后的Odoo版本中使用这两个装饰器,系统会报错。
    很多人会说,你这不是闲得没事干吗?讨论一个已经淘汰的语法应用有什么意义呢?其实,这些语法虽然被淘汰了,但是要知道最新版本的Odoo的实体类方法默认就是工作在过去 api.multi 这种模式下,而 api.model 也继续在工作。所以,我们对这些淘汰语法的讨论可以加深对当前新语法的认识。

    api.one - Odoo最被误解的语法

    api.one 的用法是Odoo中最被误解的一个。以至于到V9.0发布的时候Odoo就建议大家放弃吧,不要再乱用了, 全部用 api.multi 就好。如果不做点解释这个语法是妥妥的带着完全的误解走入坟墓的那个。

    对这个装饰器的错误理解我认为主要是因为其名字的误导,而且还存在一个跟它相对的 api.multi 。所以,大多数的人的直觉就是认为 api.one 装饰的方法就是工作在只有单个Record的情况下。而事实是正相反, api.one 设计的初衷正是为了简化处理多实例的Record Set的。比如:

    class Category(models.Model):
        _name = 'test_new_api.category'
    
        name = fields.Char(required=True)
        parent = fields.Many2one('test_new_api.category', ondelete='cascade')
        display_name = fields.Char(compute='_compute_display_name', inverse='_inverse_display_name')
    
        @api.one
        @api.depends('name', 'parent.display_name')     # this definition is recursive
        def _compute_display_name(self):
            if self.parent:
                self.display_name = self.parent.display_name + ' / ' + self.name
            else:
                self.display_name = self.name
    

    在上面这个简单的例子中,display_name 是一个计算字段,作用是将所有上级分类的名称连接显示。当在分类对象的表单视图上时 self 就是单个记录,而在Tree视图时,self 就是包含多个记录的记录集。上面的例子如果换成 api.multi 的话就要保证方法内一定要做循环,否则在Tree视图时就会报错,也就是:

    
        @api.multi
        @api.depends('name', 'parent.display_name')     # this definition is recursive
        def _compute_display_name(self):
            for rec in self:
                if rec.parent:
                    rec.display_name = rec.parent.display_name + ' / ' + rec.name
                else:
                    rec.display_name = rec.name
    

    而 api.one 则可以**“假装”** self 是单条记录这样处理,装饰器会自动对记录集做循环,并将函数结果归集到列表中。这其实的确会让程序员省事不少,因为在Odoo中绝大多数情况类方法要考虑对多记录的循环处理的。所以因为起名不慎,导致了其早夭。以后开发者就老老实实的,不厌其烦的象上面这样循环吧。

    api.multi 和 self.ensure_one()

    比如下面的例子:

      @api.multi
      def action_done(self):
          self.ensure_one()
          self.state = 'done'
          ....
    

    上面这段代码又是 multi (多个), 又是 ensure_one (保证一个) ,好分裂啊。可见,multi 并不是说我们都是工作在多实例的记录集上,而是既可能是单例记录也可能是多例记录集。比如上面例子中,这是一个表单上的确认按钮对应的方法,所以我们需要确保 self 只能是单例(否则就要做循环),这个 self.ensure_one 就是用来确保 self 不是多例的。

    幸亏在V13之后我们不用再写 @api.multi 装饰器了,默认就是工作在它所指定的方式下。否则,这种分裂语言在Odoo中真的会触目惊心。

    api.model 的用法

    搞明白了上面的概念, api.model 就不复杂了。 api.model 使用的方法一直没有发生变化。上面的使用 api.one 或 api.multi 装饰器装饰的方法,或者最新的不带装饰器(实际就是 api.multi)的方法中的 self 都是记录集,就是model所对应的数据库表中的记录。而 api.model 所装饰的方法中的 self 是指model本身。比如:

    @api.model
    def create(self):
        ...
    
    def write(self):
        ...
    

    上面 create 方法就要用 api.model 装饰,因为在调用 create 方法时还没有记录集呢。而 write 方法当然是对已有记录集的更新,所以不加装饰器(也就是隐性的 api.multi 装饰的方法)。

    希望上面的解释对您理解Odoo的API有帮助。

    【上海先安科技】(tony AT openerp.cn)

    1 Reply Last reply
    0

    Hello! It looks like you're interested in this conversation, but you don't have an account yet.

    Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

    With your input, this post could be even better 💗

    Register Login
    Reply
    • Reply as topic
    Log in to reply
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes


    • Login

    • Don't have an account? Register

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Tags
    • Popular
    • Users
    • Groups