odoo開發五大方法必須了解掌握

search、name_search、search_count、search_read、read_group方法

It mainly includes the following methods and their main uses:


search(): Called in the search view

search_count(): Called when counting records in a view

name_search(): called when searching in many2one field

search_read(): called when clicking "search more" on a many2one field

read_group(): Called when grouping the search view


search()

The search method contains several sub-methods.


Retrieve data records that meet the query conditions based on the domain

Special usage of the active field, use active_test=False to bypass

The count attribute can directly perform count statistics without needing search_count.

The _uniquify_list method will deduplicate the ids, meaning that when ids are the same, only one result will be found.


search_count()

Perform statistical counting based on the search results. If counting is needed, you can directly add the count=true attribute during the search, which makes the calculation faster.


    @api.model

    def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None):

        TRANSLATED SEGMENT:

        Performs a ``search()`` followed by a ``read()``. First search then read

        :param domain: 搜尋網域,請參閱 ``search()`` 中的 ``args`` 參數。預設為空網域,將比對所有記錄。

            Query condition; if empty, query all by default.

        :param fields: 要讀取的欄位列表,請參閱 ``read()`` 中的 ``fields`` 參數。預設為所有欄位。

            Fields to query, default to all fields

        :param offset: 要跳過的記錄數,請參閱 ``search()`` 中的 ``offset`` 參數。預設值為 0。

            Amount of data skipped

        :param limit: 要返回的最大记录数,参见 ``search()`` 中的 ``limit`` 参数。默认无限制。

            Number of query results

        :param order: 对结果进行排序的列,参见 ``search()`` 中的 ``order`` 参数。默认不排序。

            Sort criteria

        :return: 包含所詢問欄位的字典列表。

            Returns a list of dictionary values for the field

        :rtype: List of dictionaries. A list containing dictionaries

        TRANSLATED SEGMENT:

        records = self.search(domain or [], offset=offset, limit=limit, order=order)

        if not records:

            return []

 

        if fields and fields == ['id']:

            # 快捷讀取如果我們只需要ID

            return [{'id': record.id} for record in records]

 

        # read() 會忽略 active_test,但會將其轉發給任何下游的搜尋呼叫

        # (例如對於 x2m 或函數欄位),而這並非預期行為,該標誌

        # 原本可能僅用於主要的 search()。

        # read() ignores active_test, but it will forward it to any downstream search calls (e.g., for x2m or function words,

        # This is not the expected behavior, this flag may only apply to the main search().

        # TODO: 將此移至 read() 直接處理?

        if 'active_test' in self._context:

            context = dict(self._context)

            del context['active_test']

            records = records.with_context(context)

 

        result = records.read(fields)

        if len(result)

            return result

 

        # 重新排序讀取

        index = {vals['id']: vals for vals in result}

        return [index[record.id] for record in records if record.id in index]


name_search()

It is also queried by calling the _search method.


    @api.model

    def name_search(self, name='', args=None, operator='ilike', limit=100):

        name_search(name='', args=None, operator='ilike', limit=100) -> records

        搜尋顯示名稱符合指定條件的記錄

        ``name`` 模式在与给定的 ``operator`` 进行比较时,同时

        匹配可選的搜索域(``args``)。

            Search for records with a display name matching the given name "name" pattern, when compared with the given "operator" pattern, also matches the optional search field (' ' args ' ').

        This is used for example to provide suggestions based on a partial

        value for a relational field. Sometimes be seen as the inverse

        function of :meth:`~.name_get`, but it is not guaranteed to be.

            For example, it is used to provide suggested values for relational fields based on partial content. It is sometimes seen as the inverse function of '~.name_get', but this is not guaranteed.

        此方法等同於使用搜尋條件呼叫 :meth:`~.search`

        domain based on ``display_name`` and then :meth:`~.name_get` on the

        搜索結果。

            This method is equivalent to calling :meth:' ~.search to search for the domain, followed by :meth: ' ~.name_get ' on the search results.

        :param str name: the name pattern to match Name used for searching

        :param list args: 可選搜尋網域(請參閱 :meth:`~.search` 以獲取

                          syntax), specifying further restrictions Search criteria

        :param str operator: 域運算子用於匹配 ``name``,例如

                             ``'like'`` or ``'='``. Condition: like, =

        :param int limit: optional max number of records to return Number of records to query

        :rtype: list

        :return: list of pairs ``(id, text_repr)`` for all matching records.

        TRANSLATED SEGMENT:

        return self._name_search(name, args, operator, limit=limit)

 

    @api.model

    def _name_search(self, name='', args=None, operator='ilike', limit=100, name_get_uid=None):

        # private implementation of name_search, allows passing a dedicated user

        # 用於name_get部分以解決某些存取權限問題

        args = list(args or [])

        # 優化掉預設的 ``ilike ''`` 條件,該條件匹配所有內容

        if not self._rec_name:

            _logger.warning("無法執行 name_search,%s 上未定義 _rec_name", self._name)

        elif not (name == '' and operator == 'ilike'):

            args += [(self._rec_name, operator, name)]

        access_rights_uid = name_get_uid or self._uid

        ids = self._search(args, limit=limit, access_rights_uid=access_rights_uid)

        recs = self.browse(ids)

        return lazy_name_get(recs.sudo(access_rights_uid))


read_group()

Used when grouping data


    @api.model

    def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):

        TRANSLATED SEGMENT:

        取得清單檢視中按給定的 ``groupby`` 欄位分組的記錄清單

            Get the list of records grouped by the given "groupby" field in the list view

        :param domain: 列表指定搜索條件 [['field_name', 'operator', 'value'], ...]

            domain condition

        :param list fields: 清單檢視中存在的欄位清單,指定於物件上。

                每個元素可以是 'field'(欄位名稱,使用預設聚合),

                或 'field:agg'(帶有聚合函數 'agg' 的聚合欄位),

                or 'name:agg(field)' (聚合字段使用 'agg' 并作为 'name' 返回)。

                可能的聚合函數是 PostgreSQL 所提供的

                (https://www.postgresql.org/docs/current/static/functions-aggregate.html)

                and 'count_distinct',具有預期的含義。

                Fields displayed after grouping

        :param list groupby: 記錄將根據其進行分組的groupby描述列表。  

                A groupby description is either a field (then it will be grouped by that field)

                or a string 'field:groupby_function'. Right now, the only functions supported

                are 'day', 'week', 'month', 'quarter' or 'year', and they only make sense for 

                date/datetime 欄位。

                Grouping conditions

        :param int offset: 可選的要跳過的記錄數

            Skip how many query records

        :param int limit: 可选的最大返回记录数

            Number of records returned

        :param list orderby: 可選 ``order by`` 規範,用於

                             覆寫自然排序順序的

                             groups, 另請參閱 :py:meth:`~osv.osv.osv.search`

                             (目前仅支持多对一字段)

            Sort criteria

        :param bool lazy: 若為真,結果僅按第一個 groupby 分組,且 

                剩余的groupby被放入__context键中。如果为false,所有groupby都将

                一次通話完成。

                Whether to abandon lazy loading: If true, the result is only grouped by the first groupby and the remaining groups are placed in the __context key. If false, all groups are handled in a single call.

        :return: list of dictionaries(one dictionary for each record) containing:

                    * 由 ``groupby`` 參數中的欄位所分組的欄位值

                    * __domain: 指定搜尋條件的元組列表

                    * __context: 字典,包含類似 ``groupby`` 的引數

        :rtype: [{'field_name_1': value, ...]

        :raise AccessError: * 如果使用者對所請求的物件沒有讀取權限

                            * 如果使用者嘗試繞過對所請求物件的讀取存取規則

        TRANSLATED SEGMENT:

        result = self._read_group_raw(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy)

 

        groupby = [groupby] if isinstance(groupby, pycompat.string_types) else list(OrderedSet(groupby))

        dt = [

            f for f in groupby

            if self._fields[f.split(':')[0]].type in ('date', 'datetime')    # e.g. 'date:month'

        ]

 

        # 迭代所有結果並替換「完整」的日期/日期時間值

        # (range, label) 僅以格式化後的標籤進行原地替換

        for group in result:

            for df in dt:

                # 可能按日期(時間)欄位分組,該欄位在某些情況下為空

                # records, in which case as with m2o the _raw value will be

                # `False` 而不是一个 (值, 标签) 对。在这种情况下,

                # 保留 `False` 值不變

                if group.get(df):

                    group[df] = group[df][1]

        return result

 

    @api.model

    def _read_group_raw(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):

        self.check_access_rights('read')

        # Parse domain into SQL query statement

        query = self._where_calc(domain)

        # Extract the field storing the database

        fields = fields or [f.name for f in self._fields.values() if f.store]

 

        groupby = [groupby] if isinstance(groupby, pycompat.string_types) else list(OrderedSet(groupby))

        groupby_list = groupby[:1] if lazy else groupby

        annotated_groupbys = [self._read_group_process_groupby(gb, query) for gb in groupby_list]

        groupby_fields = [g['field'] for g in annotated_groupbys]

        order = orderby 或 ','.join([g for g in groupby_list])

        groupby_dict = {gb['groupby']: gb for gb in annotated_groupbys}

 

        self._apply_ir_rules(query, 'read')

        for gb in groupby_fields:

            assert gb in self._fields, "未知字段 %r 在 'groupby' 中" % gb

            gb_field = self._fields[gb].base_field

            assert gb_field.store and gb_field.column_type, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True"

 

        aggregated_fields = []

        select_terms = []

 

        for fspec in fields:

            if fspec == 'sequence':

                繼續

 

            match = regex_field_agg.match(fspec)

            如果沒有匹配:

                raise UserError(_("無效的欄位規格 %r。") % fspec)

 

            name, func, fname = match.groups()

            if func:

                # 我們有 'name:func' 或 'name:func(fname)' 兩種形式

                fname = fname 或 name

                field = self._fields[fname]

                if not (field.base_field.store and field.base_field.column_type):

                    raise UserError(_("無法彙總欄位 %r。") % fname)

                if not func.isidentifier():

                    raise UserError(_("無效的聚合函數 %r。") % func)

            else:

                # 我們有 'name',檢索該欄位上的聚合器

                field = self._fields.get(name)

                if not (field and field.base_field.store and

                        field.base_field.column_type 和 field.group_operator):

                    繼續

                func, fname = field.group_operator, name

 

            if fname in groupby_fields:

                繼續

            if name in aggregated_fields:

                raise UserError(_("輸出名稱 %r 被使用了兩次。") % name)

            aggregated_fields.append(name)

 

            expr = self._inherits_join_calc(self._table, fname, query)

            if func.lower() == 'count_distinct':

                term = 'COUNT(DISTINCT %s) AS "%s"' % (expr, name)

            else:

                term = '%s(%s) AS "%s"' % (func, expr, name)

            select_terms.append(term)

 

        for gb in annotated_groupbys:

            select_terms.append('%s as "%s" ' % (gb['qualified_field'], gb['groupby']))

 

        groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query)

        from_clause, where_clause, where_clause_params = query.get_sql()

        if lazy and (len(groupby_fields) >= 2 or not self._context.get('group_by_no_leaf')):

            count_field = groupby_fields[0] if len(groupby_fields) >= 1 else '_'

        else:

            count_field = '_'

        count_field += '_count'

 

        prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else ''

        prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else ''

 

        query = """

            SELECT min("%(table)s".id) AS id, count("%(table)s".id) AS "%(count_field)s" %(extra_fields)s

            從 %(from)s

            %(where)s

            %(groupby)s

            %(orderby)s

            %(limit)s

            %(offset)s

        % {

            'table': self._table,

            'count_field': count_field,

            'extra_fields': prefix_terms(',', select_terms),

            'from': from_clause,

            'where': prefix_term('WHERE', where_clause),

            'groupby': prefix_terms('GROUP BY', groupby_terms),

            'orderby': prefix_terms('ORDER BY', orderby_terms),

            'limit': prefix_term('LIMIT', int(limit) if limit else None),

            'offset': prefix_term('OFFSET', int(offset) if limit else None),

        }

        self._cr.execute(query, where_clause_params)

        fetched_data = self._cr.dictfetchall()

 

        如果沒有 groupby_fields:

            return fetched_data

 

        self._read_group_resolve_many2one_fields(fetched_data, annotated_groupbys)

 

        data = [{k: self._read_group_prepare_data(k, v, groupby_dict) for k, v in r.items()} for r in fetched_data]

 

        if self.env.context.get('fill_temporal') and data:

            data = self._read_group_fill_temporal(data, groupby, aggregated_fields,

                                                  annotated_groupbys)

 

        result = [self._read_group_format_result(d, annotated_groupbys, groupby, domain) for d in data]

 

        if lazy:

            # 目前,read_group 僅在惰性模式(預設)下填充結果。

            # 如果您需要在「急切」模式下保留空群組,則

            # 方法 _read_group_fill_results 需要完全重新實作

            # 以合理的方式 

            result = self._read_group_fill_results(

                domain, groupby_fields[0], groupby[len(annotated_groupbys):],

                aggregated_fields, count_field, result, read_group_order=order,

            )

        return result

 

Original link: https://blog.csdn.net/tsoTeo/article/details/105728776

关于我们

​我们致力于帮助中小企业实现数字化转型,我们的团队由一群充满激情和创新思维的专业人士组成,他们具备丰富的行业经验和技术专长。

扫一扫获取顾问以及手册

標籤
归档
登入 發表評論
Odoo 招聘流程指南:從尋覓人才到員工入職的全流程閉環
現代企業在招聘過程中普遍面臨流程繁瑣、溝通效率低下以及候選人數據分散等挑戰。