Odoo 的一项强大之处是无需直接修改所扩展模块的代码即可添加功能。这都归功于与自身代码组件相独立的功能继承。对模块的扩展可通过继承机制实现,以已有对象的修改层的形式。这些修改可以发生在每个层面,包括模型、视图和业务逻辑层面。我们不是直接修改原有模块,而是新建一个模块,采用所要做的修改在已有模块上新增一层。
上一章讲解了如何从零开始创建应用。本章中我们将学习如何创建继承自已有应用或模块的模块,并使用原有的内核或社区功能。
为此,我们会讲解如下内容:
学习项目-扩展图书应用
对已有模型新增字段
使用经典的in-place继承来扩展模型
其它模型继承机制
视图和数据继承
网页继承
学习完本章后,读者可以对已有Odoo应用创建继承模块。可以对应用的任一组件做出修改:模型、视图、业务逻辑代码、网页控制器和网页模板。
开发准备
本文要求可通过命令行来启动 Odoo 服务。
代码将在第三章 Odoo 15开发之创建第一个 Odoo 应用的基础上进行修改。通过该篇的学习我们已在插件路径添加了代码并在数据安装了library_app模块。
本章对项目新增library_member 插件模块。相应的代码请见GitHub 仓库的ch04 目录。
学习项目-扩展图书馆应用
在第三章 Odoo 15开发之创建第一个 Odoo 应用中我们创建了一个图书应用的初始模块,可供查看图书清单。现在我们要对图书应用进行扩展添加图书会员并允许他们借书。这需要创建一个扩展模块library_member。
我们要提供如下的功能:
图书可进行能否借阅的控制。该信息要在图书表单和网站的目录页面显示。
一些图书会员数据,以及图书会员卡号和个人数据,如姓名、地址和email。
应在借阅表单提供会员发消息和社交功能,包括计划活动微件,使协作更为流畅。
后面我们会引入一个功能让会员可从图书馆借书,但这不在当前的讨论范畴。在后面的几章中会逐步展开。
图书
以下是要对图书所要做的技术修改的汇总:
添加一个Is Available? 字段。目前通过手动管理,以后会自动化。
扩展 ISBN 验证逻辑来同时支持10位数的ISBN。
扩展图书目录页来标识不可借阅图书并允许用户过滤出可借图书
会员
以下是要对图书会员所要做的技术修改的汇总:
添加一个新模型来存储姓名、卡号和 Email、地址一类的联系信息
添加社交讨论和计划活动功能
首先在library_app 同级目录创建一个library_member 目录作为扩展模块,并在其中添加两个文件,一个__init__.py
空文件和一个包含如下内容的__manifest__.py
文件:
{
'name': 'Library Members',
'description': 'Manage people who will be able to borrow books.',
'author': 'Alan Hou',
'depends': ['library_app'],
'application': False,
}
接着我们就可以开发功能了。第一个任务是常用的简单需求:对已有模型新增字段。这正好是介绍Odoo继承机制的好机会。
对已有模型新增字段
第一步我们来为Book模型添加is_available 布尔型字段。当前它只是一个简单的可编辑字段,但在之后我们会将其变成自动根据所借阅和归还的图书来赋值。
要继承已有模型,需要在 Python 类中添加一个_inherit 属性来标明所继承的模型。新类继承父 Odoo 模型的所有功能,仅需在其中声明要做的修改。可以认为这类继承是对已有模型的引用并在插入了一些修改。
通过继承为模型插入新字段
继承模型是通过 Python类以及 Odoo自有的继承机制,使用_inherit 类属性进行声明。_inherit 属性标明所继承的模型。所声明的调用抓取父 Odoo 模型的所有功能,仅需声明要做修改的部分。
编码指南推荐为每个模型创建一个 Python 文件,因此我们添加library_member/models/library_book.py文件来继承原模型。首先创建__init__.py
文件来导入该文件:
1、添加library_member/__init__.py
文件来导入 models 子文件夹
from . import models
2、添加library_member/models/__init__.py
文件,导入models 子文件夹中中的文件:
from . import library_book
3、创建library_member/models/library_book.py
文件来继承library.book模型:
from odoo import fields, models
class Book(models.Model):
_inherit = 'library.book'
is_available = fields.Boolean('Is Available?')
此处我们使用了_inherit 类属性来声明所继承模型。注意我们并没有使用到其它类属性,连_name 也没使用。除非想要做出修改,否则不需要使用这些属性。
小贴士:_name 是模型标识符,如果修改会发生什么呢?其实你可以修改,这时它会创建所继承模型的拷贝,成为一个新模型。这叫作原型继承,本文后面通过原型拷贝模型一节 会讨论。
可以把它看成是引用了中央仓库中的一个模型定义,然后在其内进行修改。修改包含添加字段、修改已有字段、修改模型类属性或添加带有新业务逻辑的方法。
要在数据表中添加新增模型字段,必须要先安装插件模块。如果一切顺利的话,就可以通过Technical > Database Structure > Models 菜单查看到library.book 模型中新增了这一字段。
对表单视图添加字段
表单、列表和搜索视图通过XML数据结构定义。需要一种修改 XML 的方式来继承视图。也即要定位到 XML 元素然后对该处进行修改。
所继承视图的 XML 数据记录和普通视图中相似,多了一个 inherit_id 属性来引用所要继承的视图。
下面我们继承图书视图并添加is_available 字段。
首先要查找待继承的视图的XML ID.通过Settings > Technical > User Interface > Views 菜单来查看。图书表单的XML ID是library_app.view_form_book 。
然后还要找到要插入修改的XML元素。我们选择在ISBN 字段之后添加Is Available? 字段。通常通过name 属性定位元素。此处为
。
我们添加XML文件,即views/book_view.xml 来继承 Partner 视图,内容如下:
Book: add Is Available? field
library.book
以上代码中,我们高亮显示了继承相关的元素。inherit_id 记录字段通过 ref 属性指向视图的外部标识符定位所继承的视图。
arch 包含所声明扩展点处使用的元素,一个带有name="isbn" 的
元素,同时包含position="after" 来声明位置。在扩展元素内,使用XML来添加is_available 字段。
创建完继承之后图书表单(在声明文件中添加该视图文件并升级插件)如下图:
图4.1: 添加了Is Available?字段后的图书表单
我们学习了继承的基础知识,对模型层和视图层新增了一个字段。接下来,我们将学习我们所使用的模型继承方法,即经典继承。
使用经典的in-place继承来扩展模型
可以把经典模型继承看作是一个插入(in-place)扩展。在声明了具有_inherit 属性的Python类时,它获取到了对相应模型定义的引用,然后对其添加扩展。模型定义存储在Odoo模型仓库中,我们可对其做进一步的修改。
下面我们学习如何在常用的继承用例中使用经典继承:修改已有字段的属性并扩展Python方法来添加或变更业务逻辑。
增量修改已有字段
继承模型时,可对已有字段做出增量修改。也就是只需要定义要修改或添加的属性。
我们对library_app 模块中所创建的Book模型做两处修改:
为isbn 字段添加一条提示,说明同时支持10位数和13位数的 ISBN,稍后会实现该功能
为publisher_id 字段添加数据库索引,以提升搜索效率
编辑library_member/models/library_book.py 文件,并在library.book 模型中添加如下代码:
class Book(models.Model):
...
isbn = fields.Char(help="Use a valid ISBN-13 or ISBN-10.")
publisher_id = fields.Many2one(index=True)
这会对字段的指定属性作出修改,未指定的属性保持不变。
升级模块,进入图书表单,将鼠标悬停在 ISBN 字段上,就可以看到所添加的提示信息了。index=True 这一修改的效果不太容易发现,通过开发者工具菜单的View Fields 选项或Settings > Technical > Database Structure > Models 菜单下的字段定义中可进行查看。
图4.2: 出版社字段启用了索引
继承 Python 方法对业务逻辑添加功能
Python 方法中编写的业务逻辑也可以被继承。Odoo 借用了 Python 已有的父类行为的对象继承机制。
举个实际的例子,我们将扩展图书 ISBN 的验证逻辑。在图书应用中仅能验证现代的13位ISBN,但老一些的图书可能只有10位数的 ISBN。我们继承_check_isbn() 方法来完成这种情况的验证。
在library_member/models/library_book.py 文件中添加如下代码:
from odoo import api, fields, models
class Book(models.Model):
...
def _check_isbn(self):
self.ensure_one()
isbn = self.isbn.replace('-', '')
digits = [int(x) for x in isbn if x.isdigit()]
if len(digits) == 10:
ponderators = [1, 2, 3, 4, 5, 6, 7, 8, 9]
total = sum(a * b for a, b in zip(digits[:9], ponderators))
check = total % 11
return digits[-1] == check
else:
return super()._check_isbn()
在继承类中继承方法,我们要使用相同方法名重新定义该方法,本例中即为_check_isbn() 。这个方法使用 super()来调用父类已实现的方法。本例中对应的代码为super()._check_isbn() 。
在方法继承中,我们在调用父类的super() 的前添加了自己的逻辑。这个方法验证ISBN是否为10位数。若是则执行所添加的对10位ISBN的验证。否则进入原有的13位验证逻辑。
如果想要进行测试或是书写测试用例。这里有一个10位ISBN的示例:威廉·戈尔丁所著《蝇王》的原始ISBN为0-571-05686-5。
Odoo 11中的变化 在Odoo 11中,所使用的Python版本由2.7 变为3.5 或更新版本。Python 3做出了很大的改版,不完全兼容Python 2。尤其是在Python 3中简化了super() 的语法。之前使用Python 2的Odoo版本中,super() 需要传入两个参数:类名和self ;例如super(Book, self)._check_isbn() 。
经典继承是最常用的继承机制。但Odoo还提供了其它的继承方式,用于别的场景。接下来我们一同学习。
其它模型继承机制
前面我们介绍了经典继承,可以看成是一种原地修改的扩展。这是最常用的一种方式,但Odoo框架还支持适用其它场景下几种继承机制。
分别是代理继承、型继承以及使用mixin:
代理继承 在继承的模型中嵌入另一个模型。例如,User 记录嵌入了Partner 记录,因而User 记录带有Partner 记录的所有字段,以及User 记录自身的字段。代理继承使用_inherits 属性。
原型继承 拷贝所继承模型的功能,创建一个新模型,有自己的数据表和数据。原型继承不常使用,在Odoo内置的插件模块中未有应用。使用_inherit 设置所要拷贝的模型,_name 属性为新创建模型的标识符。
Mixin类 是实现在其它模型中广泛复用功能的抽象模型。有点像是容器,可添加到其它模型中,但不单独使用。比如mail.thread 模型由mail 插件模型所提供。它实现了一个聊天窗口和发送消功能,在Odoo的多个模型中均有使用,如Partners 和销售报价。mixin 类通过Models.abstract 构建,而不是Models.model ,通过_inherit 进行使用。
下面几节会进行深入的讲解。
使用代理继承内嵌模型
使用代理继承无需复制数据即可在数据库中复用数据结构。它在继承模型中嵌入所代理模型实例。
注: 从技术角度严格地说,代理继承并不是真的对象继承,而是一种对象组合,将一个对象的一些功能代理至另一个对象,或由另一个对象提供一些功能。
关于代理继承的要点:
创建新模型记录也会创建并链接所代理模型记录。
继承模型中不存在的代理模型字段可进行读和写操作,类似关联的计算字段。
举个例子,对于内核 User模型,每条记录包含一条 Partner 记录,因此包含 Partner 中的所有字段以及User自身的一些字段。
在图书项目中,我们要添加一个图书会员模型。会员有会员卡并通过会员卡借阅读书。会员主数据应包含卡号,以及一些个信息,如email和地址。Partner 模型已包含联系和地址信息,所以最好是复用,而不去创建重复的数据结构。
按如下步骤使用代理继承在图书会员模型中加入Partner字段:
需要导入实现进程的Python文件。编辑 library_member/model/__init__.py 添加如下高亮的代码:
from . import library_book
from . import library_member
然后添加描述新的图书会员模型的Python文件:library_member/models/library_member.py ,其中包含如下代码:
from odoo import fields, models
class Member(models.Model):
_name = 'library.member'
_description = 'Library Member'
card_number = fields.Char()
partner_id = fields.Many2one(
'res.partner',
delegate=True,
ondelete='cascade',
required=True)
通过代理继承,library.member 中嵌入了所继承的模型:res.partner ,因此在新建会员记录时,会自动创建一个关联的 Partner并通过partner_id字段引用。
透过代理机制,嵌套模型的所有字段像父模型字段一样自动可用。本例中,会员模型可使用 Partner 中的所有字段,如 name , address 和 email ,以及会员自身的独有字段,如card_number 。底层Partner 字段存储于关联的 Partner 记录中,没有重复的数据结构。
代理继承仅用在数据层面,不适用于逻辑层。没有继承所继承模型的任意方法。但仍可使用点号运算符来访问,也称为点号标记,用于访问对象属性。例如,会员模型中partner_id.open_parent() 运行嵌套Partner记录的open_parent() 方法。
代理继承还有一种替代语法,使用_inherits 模型属性。这来自Odoo 8之前的老API,但仍在广泛使用。和上述代码相同效果的图书模型代码如下:
from odoo import fields, models
class Member(models.Model):
_name = "library.member"
_description = "Library Member"
_inherits = {"res.partner": "partner_id"}
card_number = fields.Char()
partner_id = fields.Many2one(
"res.partner",
ondelete="cascade",
required=True)
完成新模型的添加,还需要完成几步:添加权限ACL、菜单和一些视图。
添加权限ACL,创建library_member/security/ir.model.access.csv 文件并加入如下代码来:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_member_user,Member User Access,model_library_member,library_app.library_group_user,1,1,1,0
access_member_manager,Member Manager Access,model_library_member,library_app.library_group_manager,1,1,1,1
添加菜单项,创建library_member/views/library_menu.xml 文件并加入如下代码:
添加视图,创建library_member/views/member_view.xml 文件并加入如下代码:
Library Member Form View
library.member
Library Member List View
library.member
最后,编辑manifest文件来声明这三个新文件:
"data": [
"security/ir.model.access.csv",
"views/book_view.xml",
"views/member_view.xml",
"views/library_menu.xml"
],
如果代码编写正确,升级模块后即可使用新的图书会员模型了。
使用原型继承拷贝功能
经典继承使用_inherit 属性扩展模型。因其未修改_name 属性,可对该模型执行有效的原地变更。
如果使用_inherit 的同时修改了_name 属性,就会获得一具所继承模型的副本。这时新模型就会获得仅针对其自身的功能,不会添加到父模型中。副本模型与父模型相独立,不受父模型修改的影响,它有自有的数据表和数据。官方文档将这种继承称为原型继承 。
在实际开发中,使用_inherit 进行模型拷贝没太大用处。一般会更偏好代理继承,因为不拷贝就可复用数据结构。
在对多个父模型继承时,_inherit 的值就不单个名称,而是一个模型名列表。
这可用于将多个模型混合加入一个模型。这样我们多次使用同一模型的功能。抽象mixin类广泛使用了这种模式。在下一节中进行讨论。
使用 mixin类复用模型功能
将_inherit 属性赋值为一个模型名列表,会继承这些模型的功能。这大多时候使用的是mixin类。
mixin类 像是一些功能的容器,可供复用。它们实现通用功能,可添加至其它模型中。一般不直接单独使用。因此mixin类是基于models.AbstractModel 的抽象模型,不像models.Model 那样有实际数据表。
Odoo标准插件提供了一些有用的mixin。在代码中搜索models.AbstractModel 可以找到它们。值的一提的,也可能最常用的是以下两个mixin,由讨论(Discuss:mail 插件模型)应用提供:
mail.thread 提供在许多文档表单下方或右侧的消息面板功能(也称为聊天器-chatter ),以及消息和通知相关逻辑。
mail.activity.mixin 提供用于定义和规划待办任务的活动(activities )功能,也通过聊天器讨论微件对外暴露。
Odoo 11中的变化
activities mixin是在Odoo 11中引入的功能,在更早版本中无法使用。
聊天窗口和活动都是广泛使用的功能,在下一节中,我们会演示如何进行添加。
对模型添加消息聊天窗口和计划活动
我们来为图书会员模型添加消息聊天和活动mixin。操作步骤如下:
添加提供mixin的插件模型依赖,即mail 。
继承mail.thread 和mail.activity.mixin 这两个mixin类
在表单视图中添加字段。
我们来详细操作以上步骤:
编辑__manifest__.py
文件添加对mail 插件的依赖:
"depends": ["library_app", "mail"],
编辑library_member/models/library_member.py 文件继承mixin类,添加如下高亮的代码:
class Member(models.Model):
_name = 'library.member'
_description = 'Library Member'
_inherit = ["mail.thread", "mail.activity.mixin"]
通过添加这行代码,我们的模型就会包含这些 mixin 的所有字段和方法。
小贴士:本例中,mixin添加到了新创建的模型中。如果要将它们添加到在其它模块中创建的已有模型中,那么父模型也应出现在继承列表中,如:_inherit = ["library.member", "mail.thread", "mail.activity.mixin"] 。
最后要在图书会员表单视图中添加相关字段。编辑library_member/views/member_view.xml 文件添加如下高亮代码:
Library Member Form View
library.member
可以看到,mail 模块不仅提供了关注者、计划活动和消息的字段,还为它们提供了具体的网页客户端微件,这里都使用了。
升级模块后,图书会员视图应当如下所示:
图4.3: 图书会员表单视图
注意mixin本身不会对访问权限包括记录规则造成任何修改,有内置的记录规则 ,限制每个用户访问的记录。举个例子,如果希望用户仅浏览关注的人的记录,必须明确添加这条记录规则。
mail.thread 模型包含显示关注者Partner 的字段,名为message_partner_ids 。实现关注者访问规则需要添加一条记录规则 ,加上类似 [('message_partner_ids', 'in', [user.partner_id.id])] 条件的作用域表达式。
至此,我们学习了如何在模型和逻辑层扩展模块。下一步学习视图的继承来展示模型层的修改。
视图和数据继承
视图和其它数据组件也可通过模块继承来修改。就视图而言,通常是添加功能。视图的展示结构通过XML定义。对XML的继承,我们需要定位到所要继承的节点,然后声明在该处执行的操作,如插入XML元素。
其它的数据元素表现为数据库中写入的记录。继承模块对在其上写入,来修改一些值。
视图继承
视图使用XML定义,存储在结构字段arch 中。继承视图,我们需要定位到所要继承的节点,然后声明所做的修改,如添加XML元素。
Odoo自带继承XML的简化标记,使用希望匹配的XML标签,如
,借由一个或多个独特属性进行匹配,如name 。然后必须要添加position 属性来声明修改的类型。
回到本章之前在isbn 字段后添加内容的例子,可以使用如下代码:
除string 属性外的任意 XML 元素和属性均可用于选取继承点使用的节点,字符串属性会在生成视图期间翻译成用户所使用的语言,因此不能作为节点选择器。
ℹ️ 在9.0以前,string 属性(显示标签文本)也可作为继承定位符。在9.0之后则不再允许。这一限制主要源自这些字符串的语言翻译机制。
使用position 属性声明继承操作。可允许多种操作,如下:
inside (默认值):在所选节点内添加内容,这一节点应是
或
一类的容器
after :在选定节点之后向父节点添加内容
before :在选定节点之前向父节点添加内容
replace :替换所选节点。若使用空内容则会删除该元素。Odoo 10开始还允许使用其它标记来包裹元素,通过在内容中使用$0 来表示被替换的元素,如$0
。
attributes :修改匹配元素的属性值。内容中应包含带有一个或多个value
元素。如True
。若不带内容体,如
,则会从所选元素中删除属性。
小贴士: 虽然position="replace"可删除 XML 元素,但应避免这么做。这么做会其它其它依赖使用所删除节点作为扩展点插件元素产生崩溃。一个替代方案是,保留元素让其不可见。
将XML节点迁移到其它地方
除了attributes操作,上述定位符可与带position="move" 的子元素合并。效果是将子定位符目标节点移到父定位符的目标位置。
Odoo 12中的变化 position="move"子定位符是 Odoo 12中新增的,之前的版本中没有。
下例为将my_field 从当前位置移动到target_field 之后。
其它视图类型,如列表和搜索视图,也有 arch 字段,可以表单视图同样的方式进行继承。
使用 XPath 选取继承点
有时可能没有带唯一值的属性来用作 XML 节点选择器。在所选元素没有 name 属性时可能出现这一情况,如
、
或
视图元素。另外就是有多个带有相同 name 属性的元素,比如在看板 QWeb 视图中相同字段可能在同一 XML 模板中被多次包含。
在这些情况下我们就需要更高级的方式来定位待扩展 XML 元素。定位 XML 中元素的一种自然方式是 XPath 表达式。
以上一章中定义的图书表单视图为例,定位
元素的 XPath 表达式是//field[@name]='isbn' 。该表达式查找 name 属性等于 isbn 的
元素。
前一部分对图书表单视图继承的 XPath 写法是:
XPath 语法的更多知识请见 Python 官方文档。
如果 XPath 表达式匹配到了多个元素,仅会选取第一个作为扩展目标。所以表达式应越精确越好,使用唯一属性。name 属性最易于确保找到精确元素作为扩展点。因此在创建视图 XML 元素时添加唯一标识符就非常重要。
修改已有数据
普通数据记录也可被继承,在实际应用,通常是重写已有值。这时我们只需定位到需写入的记录,以及更新的字段和值。无需使用XPath表达式,因为我们并不是像对视图那样修改XML arch 结构。
数据加载元素执行对 y 模型的插入或更新操作:若不存在记录 x,则创建,否则被更新/覆盖。
其它模块中的记录可通过.
全局标识符访问,因此一个模块可以更新其它模块创建的记录。
小贴士: 点号(. )是保留符号,用于分隔模块名和对象标识符。所以在标识符名中不能使用点号,而应使用下划线(_ ) 字符。
举个例子,我们将 User 安全组的名称修改为 Librarian 。对应修改library_app 模块中创建的记录,使用的是library_app.library_group_user 标识符。
添加library_member/security/library_security.xml 并加入如下代码:
Librarian
这里我们使用了一个
元素,仅写了 name 字段。可以认为这是对该字段的一次写操作。
小贴士: 使用
元素时,可以选择要执行写操作的字段,但对简写元素则并非如此,如
和
。它们需要提供所有的属性,漏写任何一个都会将对应字段置为空值。但可使用
为原本通过简写元素创建的字段设置值。
刻在声明文件data 中加入security/library_security.xml 。然后更新模块即可看到用户组名称的修改。
继承视图让我们可以对后台展示层做出修改。但对前台网页也可做同样的操作。在下一节中进行讲解。
网页继承
可扩展性是Odoo框架的一个关键设计选择,Odoo的网页组件同样可进行继承。所以可对Odoo网页控制器和模板进行扩展。
第三章 Odoo 15开发之创建第一个 Odoo 应用中所创建的图书应用中,有一个图书目录页面,可进行改进。
我们会对其进行扩展来使用在图书会员模块中添加的图书可用性:
在控制器端添加对查询参数的支持,访问/library/books?available=1 过滤出可借阅图书
在模板端,指定不可借阅图书
先来继承网页控制器。
继承网页控制器
网页控制器处理网页请求并渲染页面返回响应。应关注展示逻辑,不处理业务逻辑,业务逻辑在模型方法中处理。
支持参数或URL路由属于网页展示部分,适合用网页控制器处理。
这里会扩展/library/books 端点来支持查询字符串参数available=1 ,稍后用于过滤图书目录来仅显示可借阅的图书。
要继承已有控制器,需导入创建它的原始对象,基于它声明一个Python类,然后实现包含新增逻辑的类方法,
在library_member/controllers/main.py 文件中添加继承控制器的代码如下:
from odoo import http
from odoo.addons.library_app.controllers.main import Books
class BookExtended(Books):
@http.route()
def list(self, **kwargs):
response = super().list(**kwargs)
if kwargs.get('available'):
Book = http.request.env['library.book']
books = Book.search([('is_available', '=', True)])
response.qcontext['books'] = books
return response
按如下步骤添加控制器代码:
添加 library_member/controllers/main.py 文件,确保其包含上面的代码。
在控制器子目录中添加library_member/__init__.py 文件让新增的Python文件在模块中可导入:
from . import models
from . import controllers
在library_member/controllers/__init__.py 中添加如下代码:
from . import main
之后,访问http://localhost:8069/library/books?available=1,应该会只展示勾选了Is Available? 字段的图书。
下面我们来回顾控制器扩展代码,理解其实现原理。
所要继承的控制器Books ,最初在library_app 模块的controllers/main.py 文件中声明。因此需要导入odoo.addons.library_app.controllers.main 来引用该文件。
这与模型不同,模型有一个中央仓库可以获取任意模型类的引用,如self.env['library.book'] ,无需知识具体实现它的文件。控制器没有这样的仓库,需要知道是哪个模块和文件实现了控制器,方可对其扩展。
然后基于原来的Books 声明了一个BooksExtended 类。类名不具关联性,仅是继承和扩展原类的一个载体。
再后我们(重)定义了一个待继承的控制器方法,本例为list() 。它至少需要一个简单的@http.route() 装饰器来保持路由为活跃状态。如果不带参数,将会保留父类中定义的路由。但也可以为@http.route() 装饰器添加参数,来重新定义或替换类路由。
list() 方法带有**kwargs 参数,捕获所有kwargs 字典中的参数。这些是 URL 中给定的参数,如?available=1 。
小贴士 :**kwargs 参数纳入所有可能无需使用的给定参数,但会让我们的URL可以兼容预期外的URL参数。如若选择指定具体参数,在设置了其它参数时,在调用相应控制器时会立刻失败,返回一条内部错误。
list()方法的代码一开始使用了 super() 来调用相应父类方法。返回由父类方法计算的Response 对象,包括待渲染的属性和模块,template ,以及渲染时使用的上下文qcontext 。但HTML尚待生成。仅在控制器完成运行时才生成HTML。因此在完成最终渲染前还可以修改Response 属性。
该方法检测kwargs 中available 键的非空值。如果找到,会过滤掉不可借阅图书,在记录集中更新qcontext 。因此,在控制器处理完成时,HTML会使用更新后的图书记录进行渲染,仅包含可借阅图书。
继承 QWeb 模板
网页模板为XML文档,和其它Odoo视图类型一样可以使用选择器表达式,像我们在其实视图类型如表单中使用那样。QWeb模板通常更为复杂,因糨会包含更多的HTML元素,因此大多数据时候会使用更多样的XPath 表达式。
要修改网页的实际展示,就需要继承所使用的 QWeb 模板。我们将继承library_app.book_list_template 来展示更多有关不可借阅图书的信息。
QWeb继承是一个元素,使用额外inherit_id 属性来标识待继承的QWeb模板。本例中为library_app.book_list_template 。
执行如下步骤:
添加library_member/views/book_list_template.xml 文件并加入如下代码:
(Not Available)
以下的示例使用了xpath 标记。注意在本例我们也可以使用等效的简化标记,即
在插件声明文件(即library_member/__manifest__.py )中声明新增的数据文件:
"data": [
"security/library_security.xml",
"security/ir.model.access.csv",
"views/book_view.xml",
"views/member_view.xml",
"views/library_menu.xml",
"views/book_list_template.xml",
],
此时访问http://localhost:8069/library/books应该会对不可借阅图书显示额外的视觉信息(not available)。网页长下面这样:
图4.4: 包含可借阅信息的图书列表网页
至此完结了如何继承从数据模型至用户界面元素各种类型Odoo组件的回顾。
小结
扩展性是 Odoo 框架的一个重要功能。我们可以构建插件模块,对Odoo中需要在不同层实现功能的已有插件修改或添加功能。通过继承,我们的项目可以按整洁、模块化的方式复用和扩展第三方插件模块。
模型层中,我们使用_inherit 模型属性来引用已有模型,然后在原处执行修改。模型内的字段对象还支持增量定义,这样可对已有字段重新声明,仅修改属性。
其它的模型继承机制允许我们复用数据结构和业务逻辑。代理继承通过多对一关联字段上的delegate=True 属性(或老式的 inherits 模型属性),来让关联模型的所有字段可用,并复用它们的数据结构。原型继承使用_inherit 属性加其它模型,来复制这些模型的功能(数据结构定义和方法),并可使用抽象 mixin 类,提供一系列像文档讨论消息和关注者的可复用功能。
视图层中,视图结构通过 XML 定义,(使用 XPath 或 Odoo 简化语法)定位 XML 元素来进行继承及添加 XML代码段。其它由模块创建的记录也可由继承模块修改,仅需引用对应的完整 XML ID 并在相应的字段上执行写操作。
业务逻辑层中,可使用模型继承相同的机制来进行继承,以及重新声明要继承的方法。在方法内,Python 的super() 函数可用于调用所继承方法的代码,添加代码可在其之前或之后运行。
对于前端网页,控制器中的展示逻辑继承方式和模型方法相似,网页模板也是包含 XML 结构的视图,因此可以像其它视图类型一样的被继承。
下一章中,我们将更深入学习模型,探索模型提供给我们的所有功能。
扩展阅读
以下是官方文档的其它参考,可对模块扩展和继承机制的知识进行补充:
模型继承
视图继承
网页控制器
你可能感兴趣的:(Odoo开发手册&指南,python)
Python:基于Scapy的深度包分析与网络攻击防御方案
Lethehong
Python在手 bug溜走!码农的快乐 你不懂~ python scapy syn dns
嗨,我是Lethehong!立志在坚不欲说,成功在久不在速欢迎关注:点赞⬆️留言收藏欢迎使用:小智初学计算机网页AI感谢这位博主提出的问题,如果在以后的文章中,大家有其他相关的问题,也可以积极的在评论区评论出来,博主我会的,我会积极的收纳问题,并及时的做出回应!目录1.环境准备2.基础流量捕获3.深度协议解析4.异常流量检测逻辑4.1SYNFlood检测4.2DNS放大攻击检测5.高级分析技术5.
Python之json模块的序列化和反序列化
如梦@_@
python基础
序列化:可以理解为压缩反序列化:可以理解为解压Python中序列化和反序列化其实就是一个正反两个过程。序列化就是将Python对象转化为json格式,因为Python对象只有Python语言能够识别,如果想把数据发给Java代码写的程序,那么就识别不了,所以就有一个中间的格式:json,Java中也是一样,就是将Java的数据类型转换成json格式。反序列化就是,Python接收数据的应该是Pyt
深入解析HTTP与HTTPS:定义、架构、原理、应用场景及实战指南
CloudJourney
http https 架构
前言在互联网技术飞速发展的今天,HTTP(HypertextTransferProtocol)和HTTPS(HypertextTransferProtocolSecure)已经成为Web通信的基础协议。无论是浏览网页、提交表单,还是进行数据交互,HTTP和HTTPS都扮演着至关重要的角色。本篇博文将深入解析HTTP和HTTPS的定义、架构、原理、应用场景、常见命令体系及实战场景,帮助读者全面了解并
python3安装mysql连接_Python3使用PyMySQL连接MySQL
weixin_39814925
前提介绍:【功能实现】:1.登录本地MySQLServer创建数据库和表,Python3使用PyMySQL连接本地MySQL服务器,实现对数据库的表进行简单Insert操作。【软件配置】:1.MySQL服务器:MySQL8.0.202.Pymsql版本:Pymsql0.9.33.Python版本:Python34.NavicatforMySQL版本:Navicat115.PyCharm版本:PyC
阅读Android源码的一些姿势
weixin_34405332
2019独角兽企业重金招聘Python工程师标准>>>前面吐槽了有没有必要阅读Android源码,后面觉得只吐槽不太好,还是应该多少弄点干货。需要说明的是,Android每个系统版本的源码都会有变动,而且代码中时不时Java和Native互相穿插,追求完全看透源码意义不大,把目的定在“理解代码设计的思路,弄清各个生命周期方法调用的顺序”比较实际。日常开发中怎么阅读源码找到正确的源码IDE是日常经常
Android零基础入门第64节:揭开RecyclerView庐山真面目
weixin_33749242
移动开发 java python
2019独角兽企业重金招聘Python工程师标准>>>大家还记得之前在第38期~第50期都在学习列表控件吗,其中用了8期讲ListView的使用,相信都已经掌握好了吧。那么本期一起来学习Android5.X新增的一个列表组件,那就是RecyclerView的使用。一、RecyclerView概述从前面的学习我们知道,ListView的功能非常强大,几乎绝大部分应用程序都会使用到,虽然也学会一些方法
J-OB烧录文件深入解析与应用指南
满天乱走
本文还有配套的精品资源,点击获取简介:本文档为J-OB系列的烧录文件,创建于2020年,用于嵌入式系统中微控制器单元(MCU)的固件编程。烧录文件是将程序代码写入MCU闪存中的二进制文件,可包含固件代码、配置数据或设备驱动。本文将详细探讨烧录文件的应用,包括烧录过程、开发环境准备、代码编写、编译链接、烧录参数配置、编程器连接以及固件烧录和验证等关键步骤。1.嵌入式系统烧录文件概念嵌入式系统烧录文件
使用 Docker 部署 RabbitMQ 的详细指南
m0_74824552
面试 学习路线 阿里巴巴 docker rabbitmq 容器
使用Docker部署RabbitMQ的详细指南在现代应用程序开发中,消息队列系统是不可或缺的一部分。RabbitMQ是一个流行的开源消息代理软件,它实现了高级消息队列协议(AMQP)。本文将详细介绍如何使用Docker部署RabbitMQ,并提供一些配置和管理的技巧。1.前期准备在开始之前,请确保您的系统上已经安装了Docker。如果尚未安装,可以参考Docker官方文档或我写的前面一篇文章Cen
v3-electron-vite项目快速入门指南
罗昭贝Lovely
v3-electron-vite项目快速入门指南v3-electron-vite⭐Avue3electronadmintemplate,basedon'vite'项目地址:https://gitcode.com/gh_mirrors/v3e/v3-electron-vite本指南旨在帮助您了解并快速上手un-pany/v3-electron-vite这一基于Vue3与Vite的Electron管理
如何在Python中进行JSON数据的序列化和反序列化?
计算机学长大白
python python 开发语言
在Python中,JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python内置的json模块提供了简单易用的方法来实现数据的序列化和反序列化。下面将详细介绍如何在Python中进行JSON数据的序列化和反序列化,并给出具体的示例。1.序列化序列化是指将Python对象转换为JSON格式的字符串。json模块提供
Pytorch实现mnist手写数字识别
Zn要学习
python
>-**本文为[365天深度学习训练营]中的学习记录博客**>-**原作者:[K同学啊]**我的环境:语言环境:Python3.8编译器:JupyterLab深度学习环境:torch==1.12.1+cu113torchvision==0.13.1+cu113一、前期准备1.设置GPU如果设备上支持GPU就使用GPU,否则使用CPUimporttorchimporttorch.nnasnnimpo
python股票分析系统部署操作过程及代码实现
大懒猫软件
python 开发语言 flask plotly api restful
部署一个股票分析系统涉及多个步骤,包括后端服务、前端界面和实时数据更新。以下是一个详细的部署过程,涵盖从代码编写到服务器部署的完整步骤。1.系统架构概述后端:使用Flask提供RESTfulAPI和数据处理服务。前端:使用PlotlyDash构建动态界面,实时显示股票价格走势。数据源:从金融数据API(如AlphaVantage、YahooFinance)获取实时数据。2.系统开发步骤2.1安装必
运用python制作一个完整的股票分析系统
大懒猫软件
python 开发语言 django beautifulsoup
使用python制作一个股票分析系统,可以通过股票价格走势动态界面,实时动态监测不同类型股票的变化情况。以下是一个完整的股票分析系统开发指南,包括股票价格走势动态界面和实时监测功能。这个系统将结合网络爬虫、数据分析、机器学习和可视化技术,帮助你实时监测不同类型股票的变化情况。1.系统功能概述数据采集:使用网络爬虫技术从财经网站采集股票数据。数据处理:计算技术指标(如KDJ、BOLL)并进行数据预处
使用 Python 爬虫和 FFmpeg 爬取 B 站高清视频
大懒猫软件
python 爬虫 ffmpeg
以下是一个完整的Python爬虫代码示例,用于爬取B站视频并使用FFmpeg合成高清视频。1.准备工作确保安装了以下Python库和工具:bash复制pipinstallrequestsmoviepy2.爬取视频和音频文件B站的视频和音频文件通常是分开存储的,需要分别下载视频和音频文件,然后使用FFmpeg合成。Python复制importrequestsfrommoviepy.editorimp
python爬虫模拟点击和输入,python爬虫实战--selenium模拟登录并自动点击
半夜梳长长的头发
python爬虫模拟点击和输入
爬虫实战项目。爬虫利器:selenium的使用。任务介绍最近刚刚注册了某个网站:HDHome,该站有新手考核任务,其中有一项是需要达到魔力值5000。在魔力值获取方式中,我们看到这一项:“说谢谢=0.5个魔力值”,而网站存活种子数量达到16000+,也就意味着对每个种子说一下谢谢,轻松达到8000+的魔力值,于是,这个项目应运而生。实现思路:获取种子的页面,在每个页面中找到说谢谢的按钮,并点击后,
本地部署DeepSeek模型技术指南
Evaporator Core
apache Doris 人工智能 deepseek
DeepSeek模型是一种先进的深度学习模型,广泛应用于自然语言处理、计算机视觉等领域。为了充分利用DeepSeek模型的强大功能,许多开发者和研究人员选择在本地环境中部署该模型。本文将详细介绍如何在本地环境中部署DeepSeek模型,包括环境准备、模型下载、配置、优化以及代码实现等内容。通过本文的指导,您将能够在本地成功部署并运行DeepSeek模型。1.环境准备在部署DeepSeek模型之前,
LeetCode:142. 环形链表 II(python)
痴迷、淡然~
LeetCode LeetCode 142. 环形链表 II python
LeetCode:142.环形链表II(python)给定一个链表,返回链表开始入环的第一个节点。如果链表无环,则返回null。为了表示给定链表中的环,我们使用整数pos来表示链表尾连接到链表中的位置(索引从0开始)。如果pos是-1,则在该链表中没有环。说明:不允许修改给定的链表。示例1:输入:head=[3,2,0,-4],pos=1输出:tailconnectstonodeindex1解释:
使用Python中的LangChain库优化消息长度:从聊天历史到模型性能的全面指南
m0_57781768
python langchain easyui
使用Python中的LangChain库优化消息长度:从聊天历史到模型性能的全面指南在现代人工智能应用中,大语言模型(LLM)扮演着越来越重要的角色,尤其是在对话系统、智能助理和其他自然语言处理任务中。然而,所有的模型都有一个有限的上下文窗口,意味着它们可以处理的输入令牌(tokens)数量是有限的。当我们需要处理较长的对话历史或复杂的任务链时,如何管理传递给模型的消息长度变得至关重要。在这篇文章
Window on arm编译onnxruntime的python安装包
lpcarl
Windows on arm开发 python WOA Windows on arm onnx
Windowonarm编译onnxruntime_qnn的python安装包准备工作开始安装准备工作1.下载onnxruntime的源码gitclonehttps://github.com/microsoft/onnxruntime.git2.安装vsstudio下载visualstudio安装包,并在线安装visualstudio2022版本,安装完成后安装“c++桌面应用开发”相关的组件下载c
知识图谱neo4j—利用python进行知识入库
gcl_code
知识图谱 neo4j 知识图谱 python
知识图谱neo4j—利用python进行知识入库知识图谱—利用python进行知识入库作为一个写sql出生的菜鸡,在这里分享一下去年11月到12月之间研究的关于知识图谱的课题相关知识,由于客户的原因最终该项目没有继续进行下去,但是有些经验还是可以跟大家分享一下,理论知识就不说了,很多人已经有类似的分享了,这边分享一个我自己用python写的导入neo4j的脚本,能达到1秒入库4000条左右记录数据
JAVA和Python的区别
草莓味的¥猪
语言 java python 开发语言
一、整体区别语法结构:Java是一种面向对象的编程语言,采用了类和对象的概念,需要使用大括号“{}”来定义代码块和方法。而Python是一种动态类型的编程语言,使用缩进来表示代码块的层级结构,不需要显式地定义类和对象。编程范式:Java是一种静态类型的编程语言,需要在编译时进行类型检查,并且必须声明变量的数据类型。Python是一种动态类型的编程语言,变量的数据类型是根据赋值而确定的,不需要显式声
python的selenium库模拟输入和点击
mangge08
selenium 测试工具
使用python打开已经登录的谷歌浏览器,模拟录入文本提交数据。1、执行命令行,系统会打开浏览器,手工登录"C:\ProgramFiles\Google\Chrome\Application\chrome.exe"--remote-debugging-port=9223--user-data-dir="C:\tmp"2、下载谷歌驱动,先看谷歌版本,再谷歌地址栏输入:chrome://setting
python的django后台管理_python3 django-admin 初始化后台管理项目(mysql)
weixin_39582737
环境和工具python3djangomysqlPyCharm$python3--versionPython3.7.0$django-admin--version2.2python3和django安装django初始化项目使用django-admin来初始化一个项目$django-adminstartprojectmydjango$cdmydjango$tree.├──manage.py#与该Dja
android adb 查看系统主频,hp adb命令,查看内存,CPU主频等信息。
三木在Yummy
android adb 查看系统主频
Theadbcommandprovidesawaytogainusefulinformationaboutanumberofthesystemsconfigurationareas.Todeterminethephysicalmemory(RAM):forHP-UX10xexample:echophysmem/D|adb/stand/vmunix/dev/kmemphysmem:physmem:2
Java中代码的执行顺序(Java基础)
Java搬码工
javaSE java
在Java里,不同类型代码有着特定的执行顺序,理解这些顺序对掌握程序运行逻辑十分关键。下面将详细阐述Java中不同类型代码(静态代码块、实例代码块、构造方法、静态变量、实例变量、静态方法、实例方法等)的执行顺序。单类中的代码执行顺序当只有一个类时,代码执行顺序通常为:静态变量初始化、静态代码块、实例变量初始化、实例代码块、构造方法。classSingleClassExample{//静态变量sta
Django之admin后台管理
除却巫山不是云@
django python 后端
admin配置步骤:1.创建后台管理账号输入命令pythonmanage.pycreatesuperuser之后,设置用户名,密码,邮箱。输入命令pythonmanage.pyrunserver启动项目,打开127.0.0.1:8000/admin/进入后台管理界面,截图如下:输入设置的用户名和密码即可登录。如下所示:
掌握SQLite_轻量级数据库的全面指南
随风九天
java 匠心数据库 数据库 sqlite
1.引言1.1SQLite简介SQLite是一个嵌入式关系型数据库管理系统,它不需要单独的服务器进程或系统配置。它的设计目标是简单、高效、可靠,适用于各种应用场景,尤其是移动设备和嵌入式系统。1.2为什么选择SQLite轻量级:文件大小通常在几百KB到几MB之间。无服务器架构:不需要单独的服务器进程。跨平台支持:支持多种操作系统和编程语言。事务支持:支持ACID事务。1.3适用场景与限制适用场景:
open3d python 分割多个平面
黄晓魚
halcon3d PCL点云处理 深度神经网络 点云处理 PCL库 Open3D库 Point++模型使用 平面 算法 open3d python
测试效果废话在Open3D中,detect_planar_patches方法用于从点云数据中检测平面区域(或称为平面补丁)。这个方法通过分析点云中各点之间的法线向量和方向性来识别具有相似法线向量的点群,从而识别出潜在的平面区域。下面是对你给出的代码行中各个参数的解释:normal_variance_threshold_deg:法线向量方差阈值(以度为单位)。这个参数设定了允许的点云中法线向量方向变
ChatGPT 提示词全网最全案例汇总
编程IT圈
chatgpt 人工智能
GPT地址,收藏不迷路:https://ai.cxyquan.com/ChatGPT提示词案例分享充当旅游指南我想让你做一个旅游指南。我会把我的位置写给你,你会推荐一个靠近我的位置的地方。在某些情况下,我还会告诉您我将访问的地方类型。您还会向我推荐靠近我的第一个位置的类似类型的地方。我的第一个建议请求是“我在上海,我只想参观博物馆。”充当时间旅行指南我要你做我的时间旅行向导。我会为您提供我想参观的
Altium Designer(AD)仿真实验操作指南
逼子歌
Altium 硬件工程师笔试面试题目汇总 单片机 嵌入式硬件 硬件工程师 硬件测试 笔记 AD仿真实验 Altium Designer
目录1、创建原理图1.1创建原理图1.2点击simulate1.3仿真模块介绍2、绘制原理图2.1二极管半波整流电路仿真为例2.2放置电源模块2.3器件选择2.4放置电器元件2.5连线及GND3、设置参数3.1设置电源参数3.2波形类型3.3电源设置3.4二极管设置3.5电阻设置3.6测试探头3.7测试探头命名4、实验结果4.1运行仿真4.2实验结果4.3OperatingPoint:工作点4.4
基本数据类型和引用类型的初始值
3213213333332132
java基础
package com.array;
/**
* @Description 测试初始值
* @author FuJianyong
* 2015-1-22上午10:31:53
*/
public class ArrayTest {
ArrayTest at;
String str;
byte bt;
short s;
int i;
long
摘抄笔记--《编写高质量代码:改善Java程序的151个建议》
白糖_
高质量代码
记得3年前刚到公司,同桌同事见我无事可做就借我看《编写高质量代码:改善Java程序的151个建议》这本书,当时看了几页没上心就没研究了。到上个月在公司偶然看到,于是乎又找来看看,我的天,真是非常多的干货,对于我这种静不下心的人真是帮助莫大呀。
看完整本书,也记了不少笔记
【备忘】Django 常用命令及最佳实践
dongwei_6688
django
注意:本文基于 Django 1.8.2 版本
生成数据库迁移脚本(python 脚本)
python manage.py makemigrations polls
说明:polls 是你的应用名字,运行该命令时需要根据你的应用名字进行调整
查看该次迁移需要执行的 SQL 语句(只查看语句,并不应用到数据库上):
python manage.p
阶乘算法之一N! 末尾有多少个零
周凡杨
java 算法 阶乘 面试 效率
&n
spring注入servlet
g21121
Spring注入
传统的配置方法是无法将bean或属性直接注入到servlet中的,配置代理servlet亦比较麻烦,这里其实有比较简单的方法,其实就是在servlet的init()方法中加入要注入的内容:
ServletContext application = getServletContext();
WebApplicationContext wac = WebApplicationContextUtil
Jenkins 命令行操作说明文档
510888780
centos
假设Jenkins的URL为http://22.11.140.38:9080/jenkins/
基本的格式为
java
基本的格式为
java -jar jenkins-cli.jar [-s JENKINS_URL] command [options][args]
下面具体介绍各个命令的作用及基本使用方法
1. &nb
UnicodeBlock检测中文用法
布衣凌宇
UnicodeBlock
/** * 判断输入的是汉字 */ public static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
java下实现调用oracle的存储过程和函数
aijuans
java orale
1.创建表:STOCK_PRICES
2.插入测试数据:
3.建立一个返回游标:
PKG_PUB_UTILS
4.创建和存储过程:P_GET_PRICE
5.创建函数:
6.JAVA调用存储过程返回结果集
JDBCoracle10G_INVO
Velocity Toolbox
antlove
模板 tool box velocity
velocity.VelocityUtil
package velocity;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.c
JAVA正则表达式匹配基础
百合不是茶
java 正则表达式的匹配
正则表达式;提高程序的性能,简化代码,提高代码的可读性,简化对字符串的操作
正则表达式的用途;
字符串的匹配
字符串的分割
字符串的查找
字符串的替换
正则表达式的验证语法
[a] //[]表示这个字符只出现一次 ,[a] 表示a只出现一
是否使用EL表达式的配置
bijian1013
jsp web.xml EL EasyTemplate
今天在开发过程中发现一个细节问题,由于前端采用EasyTemplate模板方法实现数据展示,但老是不能正常显示出来。后来发现竟是EL将我的EasyTemplate的${...}解释执行了,导致我的模板不能正常展示后台数据。
网
精通Oracle10编程SQL(1-3)PLSQL基础
bijian1013
oracle 数据库 plsql
--只包含执行部分的PL/SQL块
--set serveroutput off
begin
dbms_output.put_line('Hello,everyone!');
end;
select * from emp;
--包含定义部分和执行部分的PL/SQL块
declare
v_ename varchar2(5);
begin
select
【Nginx三】Nginx作为反向代理服务器
bit1129
nginx
Nginx一个常用的功能是作为代理服务器。代理服务器通常完成如下的功能:
接受客户端请求
将请求转发给被代理的服务器
从被代理的服务器获得响应结果
把响应结果返回给客户端
实例
本文把Nginx配置成一个简单的代理服务器
对于静态的html和图片,直接从Nginx获取
对于动态的页面,例如JSP或者Servlet,Nginx则将请求转发给Res
Plugin execution not covered by lifecycle configuration: org.apache.maven.plugin
blackproof
maven 报错
转:http://stackoverflow.com/questions/6352208/how-to-solve-plugin-execution-not-covered-by-lifecycle-configuration-for-sprin
maven报错:
Plugin execution not covered by lifecycle configuration:
发布docker程序到marathon
ronin47
docker 发布应用
1 发布docker程序到marathon 1.1 搭建私有docker registry 1.1.1 安装docker regisry
docker pull docker-registry
docker run -t -p 5000:5000 docker-registry
下载docker镜像并发布到私有registry
docker pull consol/tomcat-8.0
java-57-用两个栈实现队列&&用两个队列实现一个栈
bylijinnan
java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/*
* Q 57 用两个栈实现队列
*/
public class QueueImplementByTwoStacks {
private Stack<Integer> stack1;
pr
Nginx配置性能优化
cfyme
nginx
转载地址:http://blog.csdn.net/xifeijian/article/details/20956605
大多数的Nginx安装指南告诉你如下基础知识——通过apt-get安装,修改这里或那里的几行配置,好了,你已经有了一个Web服务器了。而且,在大多数情况下,一个常规安装的nginx对你的网站来说已经能很好地工作了。然而,如果你真的想挤压出Nginx的性能,你必
[JAVA图形图像]JAVA体系需要稳扎稳打,逐步推进图像图形处理技术
comsci
java
对图形图像进行精确处理,需要大量的数学工具,即使是从底层硬件模拟层开始设计,也离不开大量的数学工具包,因为我认为,JAVA语言体系在图形图像处理模块上面的研发工作,需要从开发一些基础的,类似实时数学函数构造器和解析器的软件包入手,而不是急于利用第三方代码工具来实现一个不严格的图形图像处理软件......
&nb
MonkeyRunner的使用
dai_lm
android MonkeyRunner
要使用MonkeyRunner,就要学习使用Python,哎
先抄一段官方doc里的代码
作用是启动一个程序(应该是启动程序默认的Activity),然后按MENU键,并截屏
# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRun
Hadoop-- 海量文件的分布式计算处理方案
datamachine
mapreduce hadoop 分布式计算
csdn的一个关于hadoop的分布式处理方案,存档。
原帖:http://blog.csdn.net/calvinxiu/article/details/1506112。
Hadoop 是Google MapReduce的一个Java实现。MapReduce是一种简化的分布式编程模式,让程序自动分布到一个由普通机器组成的超大集群上并发执行。就如同ja
以資料庫驗證登入
dcj3sjt126com
yii
以資料庫驗證登入
由於 Yii 內定的原始框架程式, 採用綁定在UserIdentity.php 的 demo 與 admin 帳號密碼: public function authenticate() { $users=array( &nbs
github做webhooks:[2]php版本自动触发更新
dcj3sjt126com
github git webhooks
上次已经说过了如何在github控制面板做查看url的返回信息了。这次就到了直接贴钩子代码的时候了。
工具/原料
git
github
方法/步骤
在github的setting里面的webhooks里把我们的url地址填进去。
钩子更新的代码如下: error_reportin
Eos开发常用表达式
蕃薯耀
Eos开发 Eos入门 Eos开发常用表达式
Eos开发常用表达式
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 2014年8月18日 15:03:35 星期一
&
SpringSecurity3.X--SpEL 表达式
hanqunfeng
SpringSecurity
使用 Spring 表达式语言配置访问控制,要实现这一功能的直接方式是在<http>配置元素上添加 use-expressions 属性:
<http auto-config="true" use-expressions="true">
这样就会在投票器中自动增加一个投票器:org.springframework
Redis vs Memcache
IXHONG
redis
1. Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。
2. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。
3. Redis支持数据的备份,即master-slave模式的数据备份。
4. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
Red
Python - 装饰器使用过程中的误区解读
kvhur
JavaScript jquery html5 css
大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, Cache等。
原文链接:http://www.gbtags.com/gb/share/5563.htm
Python语言本身提供了装饰器语法(@),典型的装饰器实现如下:
@function_wrapper
de
架构师之mybatis-----update 带case when 针对多种情况更新
nannan408
case when
1.前言.
如题.
2. 代码.
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="list" index=&
Algorithm算法视频教程
栏目记者
Algorithm 算法
课程:Algorithm算法视频教程
百度网盘下载地址: http://pan.baidu.com/s/1qWFjjQW 密码: 2mji
程序写的好不好,还得看算法屌不屌!Algorithm算法博大精深。
一、课程内容:
课时1、算法的基本概念 + Sequential search
课时2、Binary search
课时3、Hash table
课时4、Algor
C语言算法之冒泡排序
qiufeihu
c 算法
任意输入10个数字由小到大进行排序。
代码:
#include <stdio.h>
int main()
{
int i,j,t,a[11]; /*定义变量及数组为基本类型*/
for(i = 1;i < 11;i++){
scanf("%d",&a[i]); /*从键盘中输入10个数*/
}
for
JSP异常处理
wyzuomumu
Web jsp
1.在可能发生异常的网页中通过指令将HTTP请求转发给另一个专门处理异常的网页中:
<%@ page errorPage="errors.jsp"%>
2.在处理异常的网页中做如下声明:
errors.jsp:
<%@ page isErrorPage="true"%>,这样设置完后就可以在网页中直接访问exc