Odoo10 使用向导时在context中关于 active_domain

tree视图全选,跳转wizard进行操作在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

sale_order 的 tree视图全选,跳转wizard进行开发票操作的时候,
当我勾选“全选复选框”,context中带有动作视图的domain,但是当我选择了几个项目并执行向导时,上下文中找不到active_domain,我这边需要的是全选又不想带active_domain
源码的accoun_invoice是继承有发邮件通知的功能

class MailComposer(models.TransientModel):
    """ Generic message composition wizard. You may inherit from this wizard
        at model and view levels to provide specific features.

        The behavior of the wizard depends on the composition_mode field:
        - 'comment': post on a record. The wizard is pre-populated via ``get_record_data``
        - 'mass_mail': wizard in mass mailing mode where the mail details can
            contain template placeholders that will be merged with actual data
            before being sent to each recipient.
    """
    _name = 'mail.compose.message'
    _inherit = 'mail.message'
    _description = 'Email composition wizard'
    _log_access = True
    _batch_size = 500

    @api.model
    def default_get(self, fields):
        """ Handle composition mode. Some details about context keys:
            - comment: default mode, model and ID of a record the user comments
                - default_model or active_model
                - default_res_id or active_id
            - reply: active_id of a message the user replies to
                - default_parent_id or message_id or active_id: ID of the
                    mail.message we reply to
                - message.res_model or default_model
                - message.res_id or default_res_id
            - mass_mail: model and IDs of records the user mass-mails
                - active_ids: record IDs
                - default_model or active_model
        """
        result = super(MailComposer, self).default_get(fields)

        # v6.1 compatibility mode
        result['composition_mode'] = result.get('composition_mode', self._context.get('mail.compose.message.mode', 'comment'))
        result['model'] = result.get('model', self._context.get('active_model'))
        result['res_id'] = result.get('res_id', self._context.get('active_id'))
        result['parent_id'] = result.get('parent_id', self._context.get('message_id'))
        if 'no_auto_thread' not in result and (result['model'] not in self.env or not hasattr(self.env[result['model']], 'message_post')):
            result['no_auto_thread'] = True

        # default values according to composition mode - NOTE: reply is deprecated, fall back on comment
        if result['composition_mode'] == 'reply':
            result['composition_mode'] = 'comment'
        vals = {}
        if 'active_domain' in self._context:  # not context.get() because we want to keep global [] domains
            vals['use_active_domain'] = True
            vals['active_domain'] = '%s' % self._context.get('active_domain')
        if result['composition_mode'] == 'comment':
            vals.update(self.get_record_data(result))

        for field in vals:
            if field in fields:
                result[field] = vals[field]

        # TDE HACK: as mailboxes used default_model='res.users' and default_res_id=uid
        # (because of lack of an accessible pid), creating a message on its own
        # profile may crash (res_users does not allow writing on it)
        # Posting on its own profile works (res_users redirect to res_partner)
        # but when creating the mail.message to create the mail.compose.message
        # access rights issues may rise
        # We therefore directly change the model and res_id
        if result['model'] == 'res.users' and result['res_id'] == self._uid:
            result['model'] = 'res.partner'
            result['res_id'] = self.env.user.partner_id.id

        if fields is not None:
            [result.pop(field, None) for field in result.keys() if field not in fields]
        return result

    @api.model
    def _get_composition_mode_selection(self):
        return [('comment', 'Post on a document'),
                ('mass_mail', 'Email Mass Mailing'),
                ('mass_post', 'Post on Multiple Documents')]

    composition_mode = fields.Selection(selection=_get_composition_mode_selection, string='Composition mode', default='comment')
    partner_ids = fields.Many2many(
        'res.partner', 'mail_compose_message_res_partner_rel',
        'wizard_id', 'partner_id', 'Additional Contacts')
    use_active_domain = fields.Boolean('Use active domain')
    active_domain = fields.Text('Active domain', readonly=True)
    attachment_ids = fields.Many2many(
        'ir.attachment', 'mail_compose_message_ir_attachments_rel',
        'wizard_id', 'attachment_id', 'Attachments')
    is_log = fields.Boolean('Log an Internal Note',
                            help='Whether the message is an internal note (comment mode only)')
    subject = fields.Char(default=False)
    # mass mode options
    notify = fields.Boolean('Notify followers', help='Notify followers of the document (mass post only)')
    auto_delete = fields.Boolean('Delete Emails', help='Delete sent emails (mass mailing only)')
    auto_delete_message = fields.Boolean('Delete Message Copy', help='Do not keep a copy of the email in the document communication history (mass mailing only)')
    template_id = fields.Many2one(
        'mail.template', 'Use template', index=True,
        domain="[('model', '=', model)]")
    # mail_message updated fields
    message_type = fields.Selection(default="comment")
    subtype_id = fields.Many2one(default=lambda self: self.sudo().env.ref('mail.mt_comment', raise_if_not_found=False).id)

触发邮件需要判断use_active_domain字段,在default_get中有此段判断赋值

if 'active_domain' in self._context:  # not context.get() because we want to keep global [] domains
            vals['use_active_domain'] = True
            vals['active_domain'] = '%s' % self._context.get('active_domain')

会导致send_mail方法中查询account_invoice模型里面sale_order视图带有的domain,报错

ValueError: Invalid field u'invoice_status' in leaf "<osv.ExtendedLeaf: (u'invoice_status', u'=', u'to invoice') on account_invoice (ctx: )>"

send_mail 方法如下:

@api.multi
def send_mail(self, auto_commit=False):
    """ Process the wizard content and proceed with sending the related
        email(s), rendering any template patterns on the fly if needed. """
    for wizard in self:
        # Duplicate attachments linked to the email.template.
        # Indeed, basic mail.compose.message wizard duplicates attachments in mass
        # mailing mode. But in 'single post' mode, attachments of an email template
        # also have to be duplicated to avoid changing their ownership.
        if wizard.attachment_ids and wizard.composition_mode != 'mass_mail' and wizard.template_id:
            new_attachment_ids = []
            for attachment in wizard.attachment_ids:
                if attachment in wizard.template_id.attachment_ids:
                    new_attachment_ids.append(attachment.copy({'res_model': 'mail.compose.message', 'res_id': wizard.id}).id)
                else:
                    new_attachment_ids.append(attachment.id)
                wizard.write({'attachment_ids': [(6, 0, new_attachment_ids)]})

        # Mass Mailing
        mass_mode = wizard.composition_mode in ('mass_mail', 'mass_post')

        Mail = self.env['mail.mail']
        ActiveModel = self.env[wizard.model if wizard.model else 'mail.thread']
        if wizard.template_id:
            # template user_signature is added when generating body_html
            # mass mailing: use template auto_delete value -> note, for emails mass mailing only
            Mail = Mail.with_context(mail_notify_user_signature=False)
            ActiveModel = ActiveModel.with_context(mail_notify_user_signature=False, mail_auto_delete=wizard.template_id.auto_delete)
        if not hasattr(ActiveModel, 'message_post'):
            ActiveModel = self.env['mail.thread'].with_context(thread_model=wizard.model)
        if wizard.composition_mode == 'mass_post':
            # do not send emails directly but use the queue instead
            # add context key to avoid subscribing the author
            ActiveModel = ActiveModel.with_context(mail_notify_force_send=False, mail_create_nosubscribe=True)
        # wizard works in batch mode: [res_id] or active_ids or active_domain
        if mass_mode and wizard.use_active_domain and wizard.model:
            res_ids = self.env[wizard.model].search(eval(wizard.active_domain)).ids
        elif mass_mode and wizard.model and self._context.get('active_ids'):
            res_ids = self._context['active_ids']
        else:
            res_ids = [wizard.res_id]

        batch_size = int(self.env['ir.config_parameter'].sudo().get_param('mail.batch_size')) or self._batch_size
        sliced_res_ids = [res_ids[i:i + batch_size] for i in range(0, len(res_ids), batch_size)]

        for res_ids in sliced_res_ids:
            batch_mails = Mail
            all_mail_values = wizard.get_mail_values(res_ids)
            for res_id, mail_values in all_mail_values.iteritems():
                if wizard.composition_mode == 'mass_mail':
                    batch_mails |= Mail.create(mail_values)
                elif wizard.composition_mode == 'single_mail':    # 新增的邮件发送类型
                    mail_values['attachment_ids'] = [(6, 0, mail_values['attachment_ids'] or [])]
                    mail_values['partner_ids'] = [(6, 0, mail_values['partner_ids'] or [])]
                    mail_values['body_html'] = mail_values['body']
                    mail_values['recipient_ids'] = mail_values['partner_ids']
                    mail_id = Mail.create(mail_values)
                    Mail.browse([mail_id]).send()   # 立即发送邮件
                else:
                    subtype = 'mail.mt_comment'
                    if wizard.is_log or (wizard.composition_mode == 'mass_post' and not wizard.notify):  # log a note: subtype is False
                        subtype = False
                    ActiveModel.browse(res_id).message_post(message_type='comment', subtype=subtype, **mail_values)

            if wizard.composition_mode == 'mass_mail':
                batch_mails.send(auto_commit=auto_commit)

    return {'type': 'ir.actions.act_window_close'}

判断有误的代码是这段

        if mass_mode and wizard.use_active_domain and wizard.model:
            res_ids = self.env[wizard.model].search(eval(wizard.active_domain)).ids

解决方法:
由于是在context中传值的,所以起初想要想办法删除全选附带的active_domain,但是context是一个frozendict,只能另辟蹊径,从判断条件入手:
重写了default_get,增加对account_invoice模型的筛选,针对这一功能,跳过account_invoice 模型有active_domain的对use_active_domain的改写

        if 'active_domain' in self._context:  # not context.get() because we want to keep global [] domains
            if result['model'] == 'account.invoice':  # ➡️暂时修改
                vals['use_active_domain'] = False
            else:
                vals['use_active_domain'] = True
                vals['active_domain'] = '%s' % self._context.get('active_domain')

我在stackoverflow上找到一篇相反的帖子
active_domain not found in context when using wizard
I’m trying to pass the active_domain to a wizard.When I use :

self.env.context.get('active_doamin',False) 

This works only when I check “select all check box” but when I select a few items and execute the wizard, I cannot find the active_domain in context, is this a bug or I’m doing it wrong?
P.S: I’m using Odoo 9

我正在尝试将 active_domain 传递给向导。当我使用:

self.env.context.get('active_doamin',False)

这仅在我选中“全选复选框”时有效,但是当我选择几个项目并执行向导时,我无法在上下文中找到 active_domain,这是一个错误还是我做错了?

四年多没有答案,希望能解决的指点一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值