<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 計算字段和默認值 [TOC] 到目前為止,我們接觸的字段都是存儲在數據庫中并直接從數據庫檢索。字段也可以通過計算獲得。在這種情況下,字段的值不是直接檢索自數據庫,而是通過調用模型的方法來實時計算獲得。要創建計算字段,需要設置它的`compute`屬性為方法名。這個計算方法通過計算`self`的每條記錄來設置字段的值。 > 注意 > `self`是一個記錄的有序集合,它支持標準的Python集合操作,如`len(self)`和`iter(self)`,加上額外的集合操作`recs1 + recs2`。迭代過程逐個提供`self`記錄,其中每個記錄本身是大小為1的集合。你可以通過點記號來訪問/分配單個記錄上的字段`record.name`。 ~~~ import random from odoo import models, fields, api class ComputedModel(models.Model): _name = 'test.computed' name = fields.Char(compute='_compute_name') @api.multi def _compute_name(self): for record in self: record.name = str(random.randint(1, 1e6)) ~~~ #### 依賴 計算字段的值通常取決于所在記錄行的其它字段的值。ORM層期望開發人員使用`depends()`裝飾器來指定計算方法的依賴性。當某些依賴關系被修改后,ORM層通過給定的依賴關系來觸發字段的重新計算。 ~~~ from odoo import models, fields, api class ComputedModel(models.Model): _name = 'test.computed' name = fields.Char(compute='_compute_name') value = fields.Integer() @api.depends('value') def _compute_name(self): for record in self: record.name = "Record with value %s" % record.value ~~~ > 練習計算字段 > > * 加入座席占用百分比字段到授課模型。 > * 在列表視圖和表單視圖中顯示這個字段 > * 以進度條的方式顯示這個字段 `openacademy/models.py` ~~~ course_id = fields.Many2one('openacademy.course', ondelete='cascade', string="Course", required=True) attendee_ids = fields.Many2many('res.partner', string="Attendees") taken_seats = fields.Float(string="Taken seats", compute='_taken_seats') @api.depends('seats', 'attendee_ids') def _taken_seats(self): for r in self: if not r.seats: r.taken_seats = 0.0 else: r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats ~~~ `openacademy/views/openacademy.xml` ~~~ <field name="start_date"/> <field name="duration"/> <field name="seats"/> <field name="taken_seats" widget="progressbar"/> </group> </group> <label for="attendee_ids"/> <tree string="Session Tree"> <field name="name"/> <field name="course_id"/> <field name="taken_seats" widget="progressbar"/> </tree> </field> </record> ~~~ #### 默認值 任何字段都可以給出默認值。在字段定義中,添加選項`default=x`,x可以是Python字面值(bool,int,float,string),也可以是一個有返回值的方法。 ~~~ name = fields.Char(default="Unknown") user_id = fields.Many2one('res.users', default=lambda self: self.env.user) ~~~ > 注意 > `self.env` 對象給出了訪問請求參數和其他有用的信息: > > * `self.env.cr` 或者 `self._cr`是數據庫游標對象,通常用于查詢數據庫 > * `self.env.uid`或者`self._uid`是當前用戶的數據庫ID > * `self.env.user`是當前用戶記錄 > * `self.env.ref(xml_id)`返回XML ID對應的記錄 > * `self.env[model_name]`返回給定模型的實例 > > 練習默認值 > > * 定義start_date默認值為今天 > * 在授課類添加字段`active`,并且設置其默認值為`True` `openacademy/models.py` ~~~ _name = 'openacademy.session' name = fields.Char(required=True) start_date = fields.Date(default=fields.Date.today) duration = fields.Float(digits=(6, 2), help="Duration in days") seats = fields.Integer(string="Number of seats") active = fields.Boolean(default=True) instructor_id = fields.Many2one('res.partner', string="Instructor", domain=['|', ('instructor', '=', True), ~~~ `openacademy/views/openacademy.xml` ~~~ <field name="course_id"/> <field name="name"/> <field name="instructor_id"/> <field name="active"/> </group> <group string="Schedule"> <field name="start_date"/> ~~~ > 注意 > Odoo 有內置規則:`active`字段值為`False`時記錄不可見 #### Onchange機制 "onchange"機制為客戶端界面提供了一種方法,當用戶在字段中填寫了值,不需要向數據庫保存任何內容,就可以更新表單。例如,假設模型有三個字段`amount`,`unit_price`和`price`,當數量和單價改變時,自動重新計算價格,并在表單界面更新。要實現這個需求,需要定義一個方法,并使用`onchange()`裝飾器,`onchange()`的參數指定了在那個字段改變時,觸發方法。其中`self`代表表單視圖中的記錄,你所做的任何更改,`self`都將立刻反應在表單上。 ~~~ <!-- content of form view --> <field name="amount"/> <field name="unit_price"/> <field name="price" readonly="1"/> ~~~ ~~~ # onchange handler @api.onchange('amount', 'unit_price') def _onchange_price(self): # set auto-changing field self.price = self.amount * self.unit_price # Can optionally return a warning and domains return { 'warning': { 'title': "Something bad happened", 'message': "It was very bad indeed", } } ~~~ 對于計算字段的值,系統內置了`onchange()`裝飾器。通過授課表單我們可以觀察到:當改變座席數和參與者人數,`taken_seats`進度條會自動更新。 > 練習 > 通過"onchange"機制顯示的驗證無效值,例如座位數為負數或者座位數多與參與者。 `openacademy/models.py` ~~~ r.taken_seats = 0.0 else: r.taken_seats = 100.0 * len(r.attendee_ids) / r.seats @api.onchange('seats', 'attendee_ids') def _verify_valid_seats(self): 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", }, } ~~~ #### 模型約束 odoo提供兩種方式實現自動驗證,`python constraints`和`sql constraints` Python約束通過方法裝飾器`constraints()`來定義,并在記錄集上調用這個方法。裝飾器參數指定了約束涉及的字段,當涉及的字段中任一發生改變時觸發方法執行。如果不滿足約束條件,該方法將引發異常: ~~~ from odoo.exceptions import ValidationError @api.constrains('age') def _check_something(self): for record in self: if record.age > 20: raise ValidationError("Your record is too old: %s" % record.age) # all records passed the test, don't return anything ~~~ > 練習添加Python約束,講師不能在自己的授課出席人中 `openacademy/models.py` ~~~ # -*- coding: utf-8 -*- from odoo import models, fields, api, exceptions class Course(models.Model): _name = 'openacademy.course' ~~~ ~~~ 'message': "Increase seats or remove excess attendees", }, } @api.constrains('instructor_id', 'attendee_ids') 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") ~~~ SQL約束通過模型屬性`_sql_constraints`進行定義。它是一個三元素的元組的列表(name, sql_definition, message),其中`name`是SQL約束名稱,`sql_definition`是約束規則,`message`是違反約束規則時的警告信息。 > 練習添加SQL約束,在Postgre SQL文檔幫助下,添加下列約束: > > * 驗證課程描述與課程標題不能完全一樣 > * 驗證課程名是唯一的 `openacademy/models.py` ~~~ session_ids = fields.One2many( 'openacademy.session', 'course_id', string="Sessions") _sql_constraints = [ ('name_description_check', 'CHECK(name != description)', "The title of the course should not be the description"), ('name_unique', 'UNIQUE(name)', "The course title must be unique"), ] class Session(models.Model): _name = 'openacademy.session' ~~~ > 練習添加重復項,因為我們為課程名稱添加了唯一性約束,所以不能再使用"復制"功能(表單->復制)。重寫"復制"方法,允許復制課程對象,將原始名稱更改為"原始名稱的副本"。 `openacademy/models.py` ~~~ session_ids = fields.One2many( 'openacademy.session', 'course_id', string="Sessions") @api.multi def copy(self, default=None): 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) _sql_constraints = [ ('name_description_check', 'CHECK(name != description)', ~~~ 作者:luohuayong 鏈接:http://www.jianshu.com/p/0c5b3e8fb160 來源:簡書 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看