Odoo 中文社区

    • 注册
    • 登录
    • 搜索
    • 版块
    • 标签
    • 热门
    • 用户
    • 群组
    1. 主页
    2. digitalsatori

    Odoo中文社区可以通过以下两个域名访问:shine-it.net , odoo.net.cn

    由于系统升迁的原因,本论坛部分较早期的内容存在格式和链接损坏失效的问题,并非本论坛系统本身的缺陷,望谅解

    本社区没有维护任何QQ群讨论组,任何与本社区同名的QQ群讨论组的言论与本社区无关!

    开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

    如果您登录系统碰到问题,请在微信公众号留言:

    • 资料
    • 关注 11
    • 粉丝 23
    • 主题 299
    • 帖子 1965
    • 最佳 52
    • 有争议的 0
    • 群组 2

    digitalsatori

    @digitalsatori

    管理员

    64
    声望
    6321
    资料浏览
    1965
    帖子
    23
    粉丝
    11
    关注
    注册时间 最后登录
    电子邮件 [email protected] 网站 openerp.cn

    digitalsatori 取消关注 关注
    总版主 管理员

    digitalsatori 发布的最佳帖子

    • Odoo的基本操作演示(视频)

      yifengkevideo fa884ec0-ca11-11e5-93d6-a3286c68f3e0/22eb47a0-e5c9-11e5-93dc-b30eefae02f1

      发布在 Odoo 培训 odoo 培训
      digitalsatori
      digitalsatori
    • RE: 请大神解释下res_model和src_model这两个属性分别代表什么意思啊???

      问题解决了,不过还是解释一下res_model和src_model, 对其他人或许有帮助,

      当一个action所操作的数据对象在操作前后是不同时,就要用到上面的两个参数了。
      src_model对应操作前的数据对象, res_model对应操作后的数据对象

      发布在 Odoo 新手求助
      digitalsatori
      digitalsatori
    • RE: odoo 实施"开箱即用": 库存条形码作业的应用

      Odoo中条码相关的应用有以下三部分的内容:

      1. 生成条码,
      2. 扫条码选择产品或单据,
      3. 快捷的库存操作(出/入库,盘点)的条码操作界面

      目前Odoo 社区版从9.0开始就没有第三项了(8.0有过)。这部分需要定制开发。

      1和2 都很简单.
      1.1 只要在产品上设置了条码,在产品标签列表打印时就可以打印出产品的条码
      0_1532483674204_Products_-_Odoo.png
      1.2 在收发货的拣货操作单上也可以打印拣货单的条码:
      0_1532483790943_Chic_IN_00004_-_Odoo.png

      1. 所有产品输入框或产品或单据搜索框内都可以通过扫描条码来定位对象。

      但是要真正快捷的使用条码来管理库存操作,要么使用企业版,要么定制条码操作界面。

      0_1532484518370_应用_-_Odoo.png

      发布在 Odoo 开发与实施交流
      digitalsatori
      digitalsatori
    • Odoo 2018 中国地区的新策略展望

      0_1515546450834_ZMNotification_—tony_openerp_cn__124_封邮件,15_封未读.png

      发布在 Odoo 新闻 odoo新闻
      digitalsatori
      digitalsatori
    • Odoo-Exp: Odoo中的external_dependencies

      在模块开发中,我们往往会引入第三方的python模块。比如当我们在对业务数据做统计分析时,可能会用到pandas Python函数库。在开发者这边我们可以安装pandas包,然后在我们的代码中可以导入pandas包中的函数或类:

       from pandas import DataFrame
      

      这样操作,开发者本地没有问题。但是如果这个Odoo模块独立发布出去,客户拿来一安装,服务器立即吐一堆的错误信息,如下面的import错误,因为客户并不知道需要先安装pandas:

      ...
      ...
      ImportError: No module named pandas
      

      怎么样在安装模块时能友好的提醒用户安装需要的Python函数包,而不是丢一堆错误信息给用户呢?

      首先在import的时候,做try...except如下:

      try:
          from pandas import DataFrame
      except ImportError:
          pass
      

      然后在__manifest__.py文件中添加external_dependencies说明,如下:

      "external_dependencies": {
          'python': ['pandas'],
          'bin': ['ffmpeg']
      },
      

      其中python key 对应的是python函数包,比如这里就是要求安装pandas函数包。另外这里还有一个bin key,它对应的则是外部命令,比如上例中的`ffmpeg``就是Linux下著名的视频/图片处理命令。

      发布在 Odoo 培训
      digitalsatori
      digitalsatori
    • 如何用python快速的算出两个时间段中重叠的天数

      比如一个时间段是:2018年1月15日到2018年5月10日
      另一个时间段是:2018年3月20日到2018年9月15日
      计算重叠天数

      >>> from datetime import datetime
      >>> from collections import namedtuple
      >>> Range = namedtuple('Range', ['start', 'end'])
      
      
      >>> r1 = Range(start=datetime(2018, 1, 15), end=datetime(2018, 5, 10))
      >>> r2 = Range(start=datetime(2018, 3, 20), end=datetime(2018, 9, 15))
      >>> latest_start = max(r1.start, r2.start)
      >>> earliest_end = min(r1.end, r2.end)
      >>> delta = (earliest_end - latest_start).days + 1
      >>> overlap = max(0, delta)
      >>> overlap
      52
      
      发布在 Python 开发
      digitalsatori
      digitalsatori
    • #Odoo-on-the-go: `@api.preupdate` 和 `@api.postupdate`

      新的提交:https://github.com/odoo/odoo/pull/31059 引入两个新的装饰器:@api.preupdate 和 @api.postupdate , 用来处理对应字段更新前和更新后的处理逻辑,这样我们就不需要覆写create, write方法。比如下面当记录中的驾驶员改变后,我们将驾驶员信息添加到历史记录中:

                  @api.postupdate('driver_id')
      	    def _postupdate_driver_history(self, vals):
      	        if 'driver_id' in vals and vals['driver_id']:
      	            self.create_driver_history(vals['driver_id'])
      
      发布在 Odoo 培训 odoo-on-the-go api
      digitalsatori
      digitalsatori
    • Odoo Studio 应用指南

      公司的兄弟写了一个Odoo Studio 应用指南:0_1512466413352_odoo-studio-instructions.pdf

      欢迎指正。

      发布在 Odoo 文档合作
      digitalsatori
      digitalsatori
    • 【转载】Python 自省指南

      IBM Developworks上的技术主题文章,对Python初学者,小鸟,老鸟都有启发

      什么是自省?

      在日常生活中,自省(introspection)是一种自我检查行为。自省是指对某人自身思想、情绪、动机和行为的检查。伟大的哲学家苏格拉底将生命中的大部分时间用于自我检查,并鼓励他的雅典朋友们也这样做。他甚至对自己作出了这样的要求:“未经自省的生命不值得存在。”

      在计算机编程中,自省是指这种能力:检查某些事物以确定它是什么、它知道什么以及它能做什么。自省向程序员提供了极大的灵活性和控制力。一旦您使用了支持自省的编程语言,就会产生类似这样的感觉:“未经检查的对象不值得实例化。”

      本文介绍了 Python 编程语言的自省能力。整个 Python 语言对自省提供了深入而广泛的支持。实际上,很难想象假如 Python 语言没有其自省特性是什么样子。在读完本文时,您应该能够非常轻松地洞察到自己 Python 对象的“灵魂”。

      在深入研究更高级的技术之前,我们尽可能用最普通的方式来研究 Python 自省。有些读者甚至可能会争论说:我们开始时所讨论的特性不应称之为“自省”。我们必须承认,它们是否属于自省的范畴还有待讨论。但从本文的主旨出发,我们所关心的只是找出有趣问题的答案。

      现在让我们以交互方式使用 Python 来开始研究。当我们从命令行启动 Python 时,就进入了 Python shell,在这里可以输入 Python 代码,而且立刻会从 Python 解释器获得响应。

      清单 1. 以交互方式启动 Python 解释器

      $ python
      Python 2.2.2 (#1, Oct 28 2002, 17:22:19)
      [GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>>
      

      在让 Python 运行起来,并看到 Python 提示符(>>>)之后,您可能想知道 Python 能识别什么字。大多数编程语言都有保留字或关键字,这些字在该语言中有特殊的意义,Python 也不例外。您可能还注意到,Python 建议我们输入 help 以获取更多信息。也许我们可以向 Python 寻求一些关于关键字的帮助。

      Python 的联机帮助实用程序

      让我们按建议的那样,通过输入 help 来开始讨论,并观察它是否会向我们提供任何关于关键字的线索:

      清单 2. 向 Python 寻求帮助

      >>> help
      Type help() for interactive help, or help(object) for help about object.
      

      因为我们不知道哪些对象可能包含关键字,所以不指定任何特定对象来尝试 help():

      清单 3. 启动帮助实用程序

      >>> help()
      Welcome to Python 2.2!  This is the online help utility.
      If this is your first time using Python, you should definitely check out
      the tutorial on the Internet at http://www.python.org/doc/tut/.
      Enter the name of any module, keyword, or topic to get help on writing
      Python programs and using Python modules.  To quit this help utility and
      return to the interpreter, just type "quit".
      To get a list of available modules, keywords, or topics, type "modules",
      "keywords", or "topics".  Each module also comes with a one-line summary
      of what it does; to list the modules whose summaries contain a given word
      such as "spam", type "modules spam".
      help>
      

      现在,我们对此的理解似乎深入了些。让我们在 help 提示符下输入 keywords:

      清单 4. 用 keywords 寻求帮助

      help> keywords
      Here is a list of the Python keywords.  Enter any keyword to get more help.
      and                 elif                global              or
      assert              else                if                  pass
      break               except              import              print
      class               exec                in                  raise
      continue            finally             is                  return
      def                 for                 lambda              try
      del                 from                not                 while
      help> quit
      You are now leaving help and returning to the Python interpreter.
      If you want to ask for help on a particular object directly from the
      interpreter, you can type "help(object)".  Executing "help('string')"
      has the same effect as typing a particular string at the help> prompt.
      >>>
      

      输入 help() 后,会看到一条欢迎消息和一些指示信息,接着是 help 提示符。在提示符下输入 keywords,则会看到一个 Python 关键字列表。我们已经获得了问题的答案,于是退出帮助实用程序,这时会看到一条简短的告别消息,并返回到 Python 提示符下。

      正如您从这个示例可以看到的,Python 的联机帮助实用程序会显示关于各种主题或特定对象的信息。帮助实用程序很有用,并确实利用了 Python 的自省能力。但仅仅使用帮助不会揭示帮助是如何获得其信息的。而且,因为本文的目的是揭示 Python 自省的所有秘密,所以我们必须迅速地跳出对帮助实用程序的讨论。

      在结束关于帮助的讨论之前,让我们用它来获得一个可用模块的列表。模块只是包含 Python 代码的文本文件,其名称后缀是 .py。如果在 Python 提示符下输入 help('modules'),或在 help 提示符下输入 modules,则会看到一长列可用模块,类似于下面所示的部分列表。自己尝试它以观察您的系统中有哪些可用模块,并了解为什么会认为 Python 是“自带电池”的。

      清单 5. 部分可用模块的列表

      >>> help('modules')
      Please wait a moment while I gather a list of all available modules...
      BaseHTTPServer      cgitb               marshal             sndhdr
      Bastion             chunk               math                socket
      CDROM               cmath               md5                 sre
      CGIHTTPServer       cmd                 mhlib               sre_compile
      Canvas              code                mimetools           sre_constants
      	<...>
      bisect              macpath             signal              xreadlines
      cPickle             macurl2path         site                xxsubtype
      cStringIO           mailbox             slgc (package)      zipfile
      calendar            mailcap             smtpd
      cgi                 markupbase          smtplib
      Enter any module name to get more help.  Or, type "modules spam" to search
      for modules whose descriptions contain the word "spam".
      >>>
      

      sys 模块

      sys 模块是提供关于 Python 本身的详尽内在信息的模块。通过导入模块,并用点(.)符号引用其内容(如变量、函数和类)来使用模块。sys 模块包含各种变量和函数,它们揭示了当前的 Python 解释器有趣的详细信息。让我们研究其中的一部分。我们要再次以交互方式运行 Python,并在 Python 命令提示符下输入命令。首先,我们将导入 sys 模块。然后,我们会输入 sys.executable 变量,它包含到 Python 解释器的路径:

      清单 6. 导入 sys 模块

      $ python
      Python 2.2.2 (#1, Oct 28 2002, 17:22:19)
      [GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>> import sys
      >>> sys.executable
      '/usr/local/bin/python'
      

      当输入一行只包含对象名称的代码时,Python 通过显示该对象的表示进行响应,对于简单对象,往往显示对象的值。在本例中,因为所显示的值是用引号括起来的,所以我们得到一条线索:sys.executable 可能是字符串对象。稍后,我们将研究确定对象类型的其它更精确的方法,但只在 Python 提示符下输入对象名称是一种迅速而又方便的自省形式。

      让我们研究 sys 模块其它一些有用的属性。
      platform 变量告诉我们现在处于什么操作系统上:

      sys.platform 属性

      >>> sys.platform
      'linux2'
      

      在当前的 Python 中,版本以字符串和元组(元组包含对象序列)来表示:

      清单 8. sys.version 和 sys.version_info 属性

      >>> sys.version
      '2.2.2 (#1, Oct 28 2002, 17:22:19) \n[GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)]'
      >>> sys.version_info
      (2, 2, 2, 'final', 0)
      

      maxint 变量反映了可用的最大整数值:

      sys.maxint 属性

      >>> sys.maxint
      2147483647
      

      argv 变量是一个包含命令行参数的列表(如果参数被指定的话)。第一项 argv[0] 是所运行脚本的路径。当我们以交互方式运行 Python 时,这个值是空字符串:

      清单 10. sys.argv 属性

      >>> sys.argv
      ['']
      

      当运行其它 Python shell 时,如 PyCrust(有关 PyCrust 更多信息的链接,请参阅参考资料),会看到类似于下面的信息:

      清单 11. 使用 PyCrust 时的 sys.argv 属性

      >>> sys.argv[0]
      '/home/pobrien/Code/PyCrust/PyCrustApp.py'
      

      path 变量是模块搜索路径,Python 在导入期间将在其中的目录列表中寻找模块。最前面的空字符串 '' 是指当前目录:

      清单 12. sys.path 属性

      >>> sys.path
      ['', '/home/pobrien/Code',
      '/usr/local/lib/python2.2',
      '/usr/local/lib/python2.2/plat-linux2',
      '/usr/local/lib/python2.2/lib-tk',
      '/usr/local/lib/python2.2/lib-dynload',
      '/usr/local/lib/python2.2/site-packages']
      

      modules 变量是一个字典,它将当前已装入的所有模块的名称映射到模块对象。如您所见,缺省情况下,Python 装入一些特定的模块:

      清单 13. sys.modules 属性

      >>> sys.modules
      {'stat': <module 'stat' from '/usr/local/lib/python2.2/stat.pyc'>,
      '__future__': <module '__future__' from '/usr/local/lib/python2.2/__future__.pyc'>,
      'copy_reg': <module 'copy_reg' from '/usr/local/lib/python2.2/copy_reg.pyc'>,
      'posixpath': <module 'posixpath' from '/usr/local/lib/python2.2/posixpath.pyc'>,
      'UserDict': <module 'UserDict' from '/usr/local/lib/python2.2/UserDict.pyc'>,
      'signal': <module 'signal' (built-in)>,
      'site': <module 'site' from '/usr/local/lib/python2.2/site.pyc'>,
      '__builtin__': <module '__builtin__' (built-in)>,
      'sys': <module 'sys' (built-in)>,
      'posix': <module 'posix' (built-in)>,
      'types': <module 'types' from '/usr/local/lib/python2.2/types.pyc'>,
      '__main__': <module '__main__' (built-in)>,
      'exceptions': <module 'exceptions' (built-in)>,
      'os': <module 'os' from '/usr/local/lib/python2.2/os.pyc'>,
      'os.path': <module 'posixpath' from '/usr/local/lib/python2.2/posixpath.pyc'>}
      

      keyword 模块

      让我们返回到关于 Python 关键字的问题。尽管帮助向我们显示了关键字列表,但事实证明一些帮助信息是硬编码的。关键字列表恰好是硬编码的,但毕竟它的自省程度不深。让我们研究一下,能否直接从 Python 标准库的某个模块中获取这个信息。如果在 Python 提示符下输入 help('modules keywords'),则会看到如下信息:

      清单 14. 同时使用 modules 和 keywords 寻求帮助

      >>> help('modules keywords')
      Here is a list of matching modules.  Enter any module name to get more help.
      keyword - Keywords (from "graminit.c")
      

      看起来,keyword 模块好象包含关键字。在文本编辑器中打开 keyword.py 文件,我们可以看到,Python 确实可以把关键字列表显式地用作 keyword 模块的 kwlist 属性。在 keyword 模块的注释中,我们还可以看到,该模块是根据 Python 本身的源代码自动生成的,这可以保证其关键字列表是准确而完整的:

      清单 15. keyword 模块的关键字列表

      >>> import keyword
      >>> keyword.kwlist
      ['and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else',
      'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
      'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield']
      

      dir() 函数

      尽管查找和导入模块相对容易,但要记住每个模块包含什么却不是这么简单。您并不希望总是必须查看源代码来找出答案。幸运的是,Python 提供了一种方法,可以使用内置的 dir() 函数来检查模块(以及其它对象)的内容。
      dir() 函数可能是 Python 自省机制中最著名的部分了。它返回传递给它的任何对象的属性名称经过排序的列表。如果不指定对象,则 dir() 返回当前作用域中的名称。让我们将 dir() 函数应用于 keyword 模块,并观察它揭示了什么:

      清单 16. keyword 模块的属性

      >>> dir(keyword)
      ['__all__', '__builtins__', '__doc__', '__file__', '__name__',
      'iskeyword', 'keyword', 'kwdict', 'kwlist', 'main']
      

      那么将它应用于我们先前讨论的 sys 模块会怎么样呢?

      清单 17. sys 模块的属性

      >>> dir(sys)
      ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__',
      '__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names',
      'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type', 'excepthook',
      'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags',
      'getrecursionlimit', 'getrefcount', 'hexversion', 'last_traceback',
      'last_type', 'last_value', 'maxint', 'maxunicode', 'modules', 'path',
      'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags',
      'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout',
      'version', 'version_info', 'warnoptions']
      

      如果不带任何参数,则 dir() 返回当前作用域中的名称。请注意,因为我们先前导入了 keyword 和 sys,所以它们出现在列表中。导入模块将把该模块的名称添加到当前作用域:

      清单 18. 当前作用域中的名称

      >>> dir()
      ['__builtins__', '__doc__', '__name__', 'keyword', 'sys']
      

      我们曾经提到 dir() 函数是内置函数,这意味着我们不必为了使用该函数而导入模块。不必做任何操作,Python 就可识别内置函数。现在,我们看到调用 dir() 后返回了这个名称 builtins。也许此处有连接。让我们在 Python 提示符下输入名称 builtins,并观察 Python 是否会告诉我们关于它的任何有趣的事情:

      清单 19. builtins 是什么?

      >>> __builtins__
      <module '__builtin__' (built-in)>
      

      因此 builtins 看起来象是当前作用域中绑定到名为 builtin 的模块对象的名称。(因为模块不是只有多个单一值的简单对象,所以 Python 改在尖括号中显示关于模块的信息。)注:如果您在磁盘上寻找 builtin.py 文件,将空手而归。这个特殊的模块对象是 Python 解释器凭空创建的,因为它包含着解释器始终可用的项。尽管看不到物理文件,但我们仍可以将 dir() 函数应用于这个对象,以观察所有内置函数、错误对象以及它所包含的几个杂项属性。

      清单 20. builtins 模块的属性

      >>> dir(__builtins__)
      ['ArithmeticError', 'AssertionError', 'AttributeError', 'DeprecationWarning',
      'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
      'FloatingPointError', 'IOError', 'ImportError', 'IndentationError',
      'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError',
      'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError',
      'OverflowError', 'OverflowWarning', 'ReferenceError', 'RuntimeError',
      'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError',
      'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError',
      'UnboundLocalError', 'UnicodeError', 'UserWarning', 'ValueError', 'Warning',
      'ZeroDivisionError', '_', '__debug__', '__doc__', '__import__', '__name__',
      'abs', 'apply', 'bool', 'buffer', 'callable', 'chr', 'classmethod', 'cmp',
      'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict',
      'dir', 'divmod', 'eval', 'execfile', 'exit', 'file', 'filter', 'float',
      'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int',
      'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list',
      'locals', 'long', 'map', 'max', 'min', 'object', 'oct', 'open', 'ord', 'pow',
      'property', 'quit', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',
      'setattr', 'slice', 'staticmethod', 'str', 'super', 'tuple', 'type', 'unichr',
      'unicode', 'vars', 'xrange', 'zip']
      

      dir() 函数适用于所有对象类型,包括字符串、整数、列表、元组、字典、函数、定制类、类实例和类方法。让我们将 dir() 应用于字符串对象,并观察 Python 返回什么。如您所见,即使简单的 Python 字符串也有许多属性:

      清单 21. 字符串属性

      >>> dir('this is a string')
      ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',
      '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',
      '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mul__', '__ne__',
      '__new__', '__reduce__', '__repr__', '__rmul__', '__setattr__', '__str__',
      'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs',
      'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace',
      'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind',
      'rindex', 'rjust', 'rstrip', 'split', 'splitlines', 'startswith', 'strip',
      'swapcase', 'title', 'translate', 'upper', 'zfill']
      

      自己尝试下列示例以观察它们返回什么。注:# 字符标记注释的开始。Python 将忽略从注释开始部分到该行结束之间的所有内容:

      清单 22. 将 dir() 运用于其它对象

      dir(42)   # Integer (and the meaning of life)
      dir([])   # List (an empty list, actually)
      dir(())   # Tuple (also empty)
      dir({})   # Dictionary (ditto)
      dir(dir)  # Function (functions are also objects)
      

      为了说明 Python 自省能力的动态本质,让我们研究将 dir() 运用于定制类和一些类实例的示例。我们将以交互方式定义自己的类,创建一些类的实例,仅向其中一个实例添加唯一的属性,并观察 Python 能否一直保存所有这些。以下是结果:

      清单 23. 将 dir() 运用于定制类、类实例和属性

      >>> class Person(object):
      ...     """Person class."""
      ...     def __init__(self, name, age):
      ...         self.name = name
      ...         self.age = age
      ...     def intro(self):
      ...         """Return an introduction."""
      ...         return "Hello, my name is %s and I'm %s." % (self.name, self.age)
      ...
      >>> bob = Person("Robert", 35)   # Create a Person instance
      >>> joe = Person("Joseph", 17)   # Create another
      >>> joe.sport = "football"       # Assign a new attribute to one instance
      >>> dir(Person)      # Attributes of the Person class
      ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
      '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',
      '__setattr__', '__str__', '__weakref__', 'intro']
      >>> dir(bob)         # Attributes of bob
      ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
      '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',
      '__setattr__', '__str__', '__weakref__', 'age', 'intro', 'name']
      >>> dir(joe)         # Note that joe has an additional attribute
      ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
      '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__repr__',
      '__setattr__', '__str__', '__weakref__', 'age', 'intro', 'name', 'sport']
      >>> bob.intro()      # Calling bob's intro method
      "Hello, my name is Robert and I'm 35."
      >>> dir(bob.intro)   # Attributes of the intro method
      ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',
      '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
      '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']
      

      文档字符串

      在许多 dir() 示例中,您可能会注意到的一个属性是 __doc__ 属性。这个属性是一个字符串,它包含了描述对象的注释。Python 称之为文档字符串或 docstring,以下是其工作原理。如果模块、类、方法或函数定义的第一条语句是字符串,那么该字符串会作为对象的 doc 属性与该对象关联起来。例如,看一下 builtins 对象的文档字符串。因为文档字符串通常包含嵌入的换行 \n,我们将使用 Python 的 print 语句,以便输出更易于阅读:

      清单 24. 模块文档字符串

      >>> print __builtins__.__doc__   # Module docstring
      Built-in functions, exceptions, and other objects.
      Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices.
      

      Python 甚至再次维持了在 Python shell 中以交互方式定义的类和方法上的文档字符串。让我们研究 Person 类及其 intro 方法的文档字符串:

      清单 25. 类和方法文档字符串

      >>> Person.__doc__         # Class docstring
      'Person class.'
      >>> Person.intro.__doc__   # Class method docstring
      'Return an introduction.'
      

      因为文档字符串提供了如此有价值的信息,所以许多 Python 开发环境都有自动显示对象的文档字符串的方法。让我们再看一个 dir() 函数的文档字符串:

      清单 26. 函数文档字符串

      >>> print dir.__doc__   # Function docstring
      dir([object]) -> list of strings
      Return an alphabetized list of names comprising (some of) the attributes
      of the given object, and of attributes reachable from it:
      No argument:  the names in the current scope.
      Module object:  the module attributes.
      Type or class object:  its attributes, and recursively the attributes of
          its bases.
      Otherwise:  its attributes, its class's attributes, and recursively the
          attributes of its class's base classes.
      

      检查 Python 对象

      我们好几次提到了“对象(object)”这个词,但一直没有真正定义它。编程环境中的对象很象现实世界中的对象。实际的对象有一定的形状、大小、重量和其它特征。实际的对象还能够对其环境进行响应、与其它对象交互或执行任务。计算机中的对象试图模拟我们身边现实世界中的对象,包括象文档、日程表和业务过程这样的抽象对象。

      类似于实际的对象,几个计算机对象可能共享共同的特征,同时保持它们自己相对较小的变异特征。想一想您在书店中看到的书籍。书籍的每个物理副本都可能有污迹、几张破损的书页或唯一的标识号。尽管每本书都是唯一的对象,但都拥有相同标题的每本书都只是原始模板的实例,并保留了原始模板的大多数特征。

      对于面向对象的类和类实例也是如此。例如,可以看到每个 Python 字符串都被赋予了一些属性,dir() 函数揭示了这些属性。在前一个示例中,我们定义了自己的 Person 类,它担任创建个别 Person 实例的模板,每个实例都有自己的 name 和 age 值,同时共享自我介绍的能力。这就是面向对象。

      于是在计算机术语中,对象是拥有标识和值的事物,属于特定类型、具有特定特征和以特定方式执行操作。并且,对象从一个或多个父类继承了它们的许多属性。除了关键字和特殊符号(象运算符,如 +、-、*、**、/、%、<、> 等)外,Python 中的所有东西都是对象。Python 具有一组丰富的对象类型:字符串、整数、浮点、列表、元组、字典、函数、类、类实例、模块、文件等。

      当您有一个任意的对象(也许是一个作为参数传递给函数的对象)时,可能希望知道一些关于该对象的情况。在本节中,我们将向您展示如何让 Python 对象回答如下问题:
      对象的名称是什么?

      这是哪种类型的对象?

      对象知道些什么?

      对象能做些什么?

      对象的父对象是谁?

      名称

      并非所有对象都有名称,但那些有名称的对象都将名称存储在其 __name__ 属性中。注:名称是从对象而不是引用该对象的变量中派生的。下面这个示例着重说明了这种区别:

      清单 27. 名称中有什么?

      $ python
      Python 2.2.2 (#1, Oct 28 2002, 17:22:19)
      [GCC 3.2 (Mandrake Linux 9.0 3.2-1mdk)] on linux2
      Type "help", "copyright", "credits" or "license" for more information.
      >>> dir()                # The dir() function
      ['__builtins__', '__doc__', '__name__']
      >>> directory = dir      # Create a new variable
      >>> directory()          # Works just like the original object
      ['__builtins__', '__doc__', '__name__', 'directory']
      >>> dir.__name__         # What's your name?
      'dir'
      >>> directory.__name__   # My name is the same
      'dir'
      >>> __name__             # And now for something completely different
      '__main__'
      

      模块拥有名称,Python 解释器本身被认为是顶级模块或主模块。当以交互的方式运行 Python 时,局部 __name__ 变量被赋予值 '__main__'。同样地,当从命令行执行 Python 模块,而不是将其导入另一个模块时,其 __name__ 属性被赋予值 '__main__' ,而不是该模块的实际名称。这样,模块可以查看其自身的 __name__ 值来自行确定它们自己正被如何使用,是作为另一个程序的支持,还是作为从命令行执行的主应用程序。因此,下面这条惯用的语句在 Python 模块中是很常见的:

      清单 28. 用于执行或导入的测试

      if __name__ == '__main__':
          # Do something appropriate here, like calling a
          # main() function defined elsewhere in this module.
          main()
      else:
          # Do nothing. This module has been imported by another
          # module that wants to make use of the functions,
          # classes and other useful bits it has defined.
      

      类型

      type() 函数有助于我们确定对象是字符串还是整数,或是其它类型的对象。它通过返回类型对象来做到这一点,可以将这个类型对象与 types 模块中定义的类型相比较:

      清单 29. 我是您的类型吗?

      >>> import types
      >>> print types.__doc__
      Define names for all type symbols known in the standard interpreter.
      Types that are part of optional modules (e.g. array) are not listed.
      >>> dir(types)
      ['BufferType', 'BuiltinFunctionType', 'BuiltinMethodType', 'ClassType',
      'CodeType', 'ComplexType', 'DictProxyType', 'DictType', 'DictionaryType',
      'EllipsisType', 'FileType', 'FloatType', 'FrameType', 'FunctionType',
      'GeneratorType', 'InstanceType', 'IntType', 'LambdaType', 'ListType',
      'LongType', 'MethodType', 'ModuleType', 'NoneType', 'ObjectType', 'SliceType',
      'StringType', 'StringTypes', 'TracebackType', 'TupleType', 'TypeType',
      'UnboundMethodType', 'UnicodeType', 'XRangeType', '__builtins__', '__doc__',
      '__file__', '__name__']
      >>> s = 'a sample string'
      >>> type(s)
      <type 'str'>
      >>> if type(s) is types.StringType: print "s is a string"
      ...
      s is a string
      >>> type(42)
      <type 'int'>
      >>> type([])
      <type 'list'>
      >>> type({})
      <type 'dict'>
      >>> type(dir)
      <type 'builtin_function_or_method'>
      

      标识

      先前我们说过,每个对象都有标识、类型和值。值得注意的是,可能有多个变量引用同一对象,同样地,变量可以引用看起来相似(有相同的类型和值),但拥有截然不同标识的多个对象。当更改对象时(如将某一项添加到列表),这种关于对象标识的概念尤其重要,如在下面的示例中,blist 和 clist 变量引用同一个列表对象。正如您在示例中所见,id() 函数给任何给定对象返回唯一的标识符:

      清单 30. 目的地……

      >>> print id.__doc__
      id(object) -> integer
      Return the identity of an object.  This is guaranteed to be unique among
      simultaneously existing objects.  (Hint: it's the object's memory address.)
      >>> alist = [1, 2, 3]
      >>> blist = [1, 2, 3]
      >>> clist = blist
      >>> clist
      [1, 2, 3]
      >>> blist
      [1, 2, 3]
      >>> alist
      [1, 2, 3]
      >>> id(alist)
      145381412
      >>> id(blist)
      140406428
      >>> id(clist)
      140406428
      >>> alist is blist    # Returns 1 if True, 0 if False
      0
      >>> blist is clist    # Ditto
      1
      >>> clist.append(4)   # Add an item to the end of the list
      >>> clist
      [1, 2, 3, 4]
      >>> blist             # Same, because they both point to the same object
      [1, 2, 3, 4]
      >>> alist             # This one only looked the same initially
      [1, 2, 3]
      

      属性

      我们已经看到对象拥有属性,并且 dir() 函数会返回这些属性的列表。但是,有时我们只想测试一个或多个属性是否存在。如果对象具有我们正在考虑的属性,那么通常希望只检索该属性。这个任务可以由 hasattr() 和 getattr() 函数来完成,如本例所示:

      清单 31. 具有一个属性;获得一个属性

      >>> print hasattr.__doc__
      hasattr(object, name) -> Boolean
      Return whether the object has an attribute with the given name.
      (This is done by calling getattr(object, name) and catching exceptions.)
      >>> print getattr.__doc__
      getattr(object, name[, default]) -> value
      Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
      When a default argument is given, it is returned when the attribute doesn't
      exist; without it, an exception is raised in that case.
      >>> hasattr(id, '__doc__')
      1
      >>> print getattr(id, '__doc__')
      id(object) -> integer
      Return the identity of an object.  This is guaranteed to be unique among
      simultaneously existing objects.  (Hint: it's the object's memory address.)
      

      可调用

      可以调用表示潜在行为(函数和方法)的对象。可以用 callable() 函数测试对象的可调用性:

      清单 32. 您能为我做些事情吗?

      >>> print callable.__doc__
      callable(object) -> Boolean
      Return whether the object is callable (i.e., some kind of function).
      Note that classes are callable, as are instances with a __call__() method.
      >>> callable('a string')
      0
      >>> callable(dir)
      1
      

      实例

      在 type() 函数提供对象的类型时,还可以使用 isinstance() 函数测试对象,以确定它是否是某个特定类型或定制类的实例:

      清单 33. 您是那些实例中的一个吗?

      >>> print isinstance.__doc__
      isinstance(object, class-or-type-or-tuple) -> Boolean
      Return whether an object is an instance of a class or of a subclass thereof.
      With a type as second argument, return whether that is the object's type.
      The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
      isinstance(x, A) or isinstance(x, B) or ... (etc.).
      >>> isinstance(42, str)
      0
      >>> isinstance('a string', int)
      0
      >>> isinstance(42, int)
      1
      >>> isinstance('a string', str)
      1
      

      子类

      我们先前提到过,定制类的实例从该类继承了属性。在类这一级别,可以根据一个类来定义另一个类,同样地,这个新类会按照层次化的方式继承属性。Python 甚至支持多重继承,多重继承意味着可以用多个父类来定义一个类,这个新类继承了多个父类。issubclass() 函数使我们可以查看一个类是不是继承了另一个类:

      清单 34. 您是我母亲吗?

      >>> print issubclass.__doc__
      issubclass(C, B) -> Boolean
      Return whether class C is a subclass (i.e., a derived class) of class B.
      >>> class SuperHero(Person):   # SuperHero inherits from Person...
      ...     def intro(self):       # but with a new SuperHero intro
      ...         """Return an introduction."""
      ...         return "Hello, I'm SuperHero %s and I'm %s." % (self.name, self.age)
      ...
      >>> issubclass(SuperHero, Person)
      1
      >>> issubclass(Person, SuperHero)
      0
      >>>
      

      检查时间

      让我们将上一节中讨论的几种检查技术结合起来。为了做到这一点,要定义自己的函数 — interrogate(),它打印有关传递给它的任何对象的各种信息。以下是代码,后面是其用法的几个示例:

      清单 35. 谁也没料到它

      >>> def interrogate(item):
      ...     """Print useful information about item."""
      ...     if hasattr(item, '__name__'):
      ...         print "NAME:    ", item.__name__
      ...     if hasattr(item, '__class__'):
      ...         print "CLASS:   ", item.__class__.__name__
      ...     print "ID:      ", id(item)
      ...     print "TYPE:    ", type(item)
      ...     print "VALUE:   ", repr(item)
      ...     print "CALLABLE:",
      ...     if callable(item):
      ...         print "Yes"
      ...     else:
      ...         print "No"
      ...     if hasattr(item, '__doc__'):
      ...         doc = getattr(item, '__doc__')
      ... 	doc = doc.strip()   # Remove leading/trailing whitespace.
      ... 	firstline = doc.split('\n')[0]
      ... 	print "DOC:     ", firstline
      ...
      >>> interrogate('a string')     # String object
      CLASS:    str
      ID:       141462040
      TYPE:     <type 'str'>
      VALUE:    'a string'
      CALLABLE: No
      DOC:      str(object) -> string
      >>> interrogate(42)             # Integer object
      CLASS:    int
      ID:       135447416
      TYPE:     <type 'int'>
      VALUE:    42
      CALLABLE: No
      DOC:      int(x[, base]) -> integer
      >>> interrogate(interrogate)    # User-defined function object
      NAME:     interrogate
      CLASS:    function
      ID:       141444892
      TYPE:     <type 'function'>
      VALUE:    <function interrogate at 0x86e471c>
      CALLABLE: Yes
      DOC:      Print useful information about item.
      

      正如您在最后一个示例中所看到的,interrogate() 函数甚至可以应用于它本身。您没有再比它更具“自省性”的工具了。

      结束语

      谁知道自省可以变得这么简单而又如此有价值?可是,我在结束时必须提出警告:不要将自省的结果误认为是万能的。有经验的 Python 程序员知道:他们不知道的东西总是比已知的更多,因此根本不可能是万能的。编程行为产生的问题多于答案。关于 Python 的唯一优点(正如我们今天在本文中所见)是它确实回答了人们的问题。至于我本人,觉得您不必因为我帮助您了解了这些 Python 必须提供的内容而酬谢我。用 Python 编程自有回报。我从爱好 Python 的同伴处获得的帮助也是不计报酬的。

      发布在 Python 开发
      digitalsatori
      digitalsatori
    • Odoo 简介 (视频)

      Odoo 101
      (试验一下嵌入视频)

      yifengkevideo fa884ec0-ca11-11e5-93d6-a3286c68f3e0/c4bf6100-ca27-11e5-93d6-a3286c68f3e0

      发布在 Odoo 培训 odoo 培训
      digitalsatori
      digitalsatori

    digitalsatori 发布的最新帖子

    • RE: 源码安装后第一次启动就报这个:“TypeError: 'NoneType' object is not subscriptable”应该怎样处理?

      @billchen0769 有没有加载第三方的全局模块server_wide_modules , post一下你的odoo.conf

      发布在 Odoo 开发与实施交流
      digitalsatori
      digitalsatori
    • RE: odoo13 如何获取明细行被选择的id

      @xinyesky Odoo的前端并不默认支持对x2M字段的多选功能。

      你可以用wizard来实现啊,在wizard中显示你红框所选的模型的过滤列表,然后就可以多选这个列表记录进行操作了。

      发布在 Odoo 新手求助
      digitalsatori
      digitalsatori
    • RE: 启动odoo报错问题(新手)

      @fengqingyang 看一下Odoo源码中的requirements.txt中对werkzeug的版本要求

      发布在 Odoo 开发与实施交流
      digitalsatori
      digitalsatori
    • RE: 求助,odoo13销售页面搜索产品字段

      @卓忆

      这估计跟产品上的name_search有关。name_search有一个100的默认limit限制。在正反向排序中获得的这100个产品不同,用它们来过滤订单可能就带来不一样的结果。

      这仅仅是我的猜测。如果上面的猜测是正确的,那么这个"bug"发生的场景是:

      用来搜索产品的字符串,可以返回的产品的数量超过100个。比如你在上面的测试里,用字母'a'来搜索产品,这个搜索结果应该会超过100个。

      你可以继续如下尝试,用一个字符串搜索产品,确保搜索出来的产品会在100以内。然后用这个字符串搜索在销售订单的产品字段上,然后再做排序处理,看看是否还会出现:排序不同搜索结果不同的现象。

      发布在 服装制衣
      digitalsatori
      digitalsatori
    • RE: 求助,odoo13销售页面搜索产品字段

      @zhang-wei918 无法排除是因为你的系统中的定制的部分影响到了搜索的结果。

      你可以在http://runbot.odoo.com中选择V13来测试,如果能还原你的问题,那就是Odoo的bug

      发布在 服装制衣
      digitalsatori
      digitalsatori
    • RE: 设置联系人查看权限后,无法进入员工模块查看员工信息。

      @Etren 问题写得非常仔细用心,排版也是本论坛第一名。非常想帮你解决问题,无奈看到我大脑爆炸🤯 。

      我只能回答你里面的一个小问题:

      @Etren 在 设置联系人查看权限后,无法进入员工模块查看员工信息。 中说:

      在技术/模型能看到模型的字段名称,记录权限中用到的字段名称结构是不是模型名称.字段名称

      不是的。就是字段名。如果你引用的是关系字段的关联对象中的字段,可以应用关系字段.关联对象字段名。 比如,我们要按客户名称来过滤销售订单,我们可以用 [('partner_id.name', 'like', 'xxxx')]形式, partner_id.name 表示订单上的客户名称

      发布在 Odoo 新手求助
      digitalsatori
      digitalsatori
    • RE: 自建模块过程中报odoo.exceptions.ValidationError: 验证视图时出错:

      没有找到模型: library.book

      View name: 馆藏图书窗体
      Error context:
      view: ir.ui.view(285,)
      xmlid: used_car_view_form
      view.model: library.book
      file: d:\odoo\server\my_addons\ usedcar \views\ used_car_views.xml

      为什么初学还要用这么混乱的命名体系搞乱自己。在二手车(usedcar)的文件里定义馆藏书(library.book)。

      然后把你的问题发在我们这 #服装制衣板块下?

      系统告诉你没有找到library.book模型。看看你修改了代码后有没有重启服务器并升级你的usedcar模块

      发布在 服装制衣
      digitalsatori
      digitalsatori
    • RE: 二开过程中新增了计算字段如果历史数据很多升级超级慢,大家是怎么克服的?

      @zerone40 要看你的这个fields1字段是派什么用场的,以及这个compute字段是怎么写的,依赖的模型和字段是什么?

      发布在 Odoo 开发与实施交流
      digitalsatori
      digitalsatori
    • RE: 刚接触odoo14,联系人权限问题求助!

      @gsj82918 可以使用记录规则来设置。具体设置可以参考这篇文章:

      https://www.odoo.com.cn/posts/record_rule_hierachical_access_rules_in_odoo/

      发布在 Odoo 新手求助
      digitalsatori
      digitalsatori
    • RE: 精简odoo13备份文件大小的若干尝试

      @卓忆 在 精简odoo13备份文件大小的若干尝试-待续 中说:

      然后 去技术 附件 里面 把那些不用的附件筛选出来后,删掉,
      再备份,发现居然 容量还是那么大,也就是说,附件几乎删光后,
      备份下来的文件容量几乎没变。。。

      Odoo的附件默认并不保存在数据库,附件在数据库中只保留附件路径,所以删除系统附件对备份容量并没有什么影响。

      发布在 Odoo 开发与实施交流
      digitalsatori
      digitalsatori