Как передать драйвер экземпляра, сгенерированный объектом selenium, в мастера в odoo - PullRequest
0 голосов
/ 23 апреля 2020

Спасибо всем, кто видел эту проблему. Я нажимаю кнопку, чтобы запустить выполнение функции, которая использует selenium в этой функции для создания driver.

. С помощью этого драйвера я могу перетаскивать изображения, нажимать кнопки, отправлять SMS-капчу на телефон, не открывая окно браузера Firefox.

Когда все это закончится, мне нужно перейти к мастеру, чтобы заставить моих пользователей вводить капчу, отправленную на телефон. Но после того, как мы загрузим мастер из odoo интерфейс и введите капчу и нажмите кнопку подтверждения, мне нужно ввести значение капчи на страницу, которую я только что открыл с driver.

Как мне получить предыдущий driver? Какие есть хорошие решения, спасибо.

Это моя функция для использования selenium

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
import selenium
from selenium.webdriver.firefox.options import Options
import time
from selenium.webdriver import ActionChains

class SaleOrderSend(models.Model)
    _name='sale.order.send'

    @api.multi
    def handel_web_send_captcha(self):

        options = Options()
        options.add_argument('--headless')


        driver = selenium.webdriver.Firefox(options=options)
        driver.get(sign_url)  
        time.sleep(15)

        ac1 = driver.find_elements_by_class_name("es-drag-seal")[0]
        ac2 = driver.find_element_by_class_name('es-sign-date-field')
        time.sleep(1)
        ActionChains(driver).drag_and_drop(ac1, ac2).perform()

        time.sleep(2)
        submit_button = driver.find_element_by_xpath("//button//span[text()='Submit']")
        submit_button.click()

        time.sleep(3)
        driver.switch_to.frame(0)
        short_message = driver.find_element_by_xpath("//a[text()='Sign']")
        short_message.click()

        time.sleep(3)
        send_code = driver.find_element_by_xpath("//div[@class='el-form-item__content']//button//span[text()='Get_Code']")
        send_code.click()

        time.sleep(2)
        driver.close()

        action = {
            'name': _("Please enter the verification code"),
            'type': 'ir.actions.act_window',
            'res_model': 'signature.code',
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new'
        }
        return action

А это мой файл py и xml файл в мастере

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
import selenium
from selenium.webdriver.firefox.options import Options
import time
from selenium.webdriver import ActionChains

class SignatureCode(models.Model):
    _name = 'signature.code'
    _description = 'Signature Code'

    sign_code = fields.Char('Sign Code')
    sign_url = fields.Char('Sign Url')

    @api.multi
    def confirm_sign_code(self):
        """
        Enter the user's captcha code into the browser page you just opened using selenium.
        :return:
        """
        sign_code = self.sign_code

        # How do I get to the previous driver?  driver = selenium.webdriver.Firefox(options=options)
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="signature_code_form_view" model="ir.ui.view">
        <field name="name">Signature Code Form View</field>
        <field name="model">signature.code</field>
        <field name="arch" type="xml">
            <form string="Signature Code Form View">
                <sheet>
                    <group>
                        <group>
                            <field name="sign_code" required="1" readonly="0"/>
                        </group>
                    </group>
                </sheet>
                <footer>
                    <button string="Confirm" name="confirm_sign_code" type="object" default_focus="1"
                            class="btn-primary"/>
                    <button string="Cancel" class="btn-default" special="cancel"/>
                </footer>
            </form>
        </field>
    </record>
</odoo>

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

Использует свойства класса Python для хранения уже сгенерированного драйвера.

В операции сначала мы нажимаем одну кнопку, чтобы перейти к мастеру, в котором у нас есть две кнопки.

Сначала нажмите первую кнопку, чтобы вызвать метод send_code, в котором мы изменяем свойство класса, например SignatureCode.driver = driver.

На втором шаге мы нажимаем кнопку подтверждения, чтобы вызвать метод confirm_sign_code, в котором мы используем driver = self.driver для обратного вызова ранее сохраненного driver в свойстве класса.

Теперь мы успешно получили ранее открытый интерфейс браузера driver и можем закрыть его в более поздней операции .

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
import selenium
from selenium.webdriver.firefox.options import Options
import time
from selenium.webdriver import ActionChains
from odoo.exceptions import UserError
import os

class SignatureCode(models.TransientModel):
    """
    This class is used to receive the captcha when signing
    """
    _name = 'signature.code'
    _description = 'Signature Code'
    driver = None # Define an initialized class property


    sign_code = fields.Char('Sign Code')
    sign_url = fields.Char('Sign Url')
    have_sent = fields.Boolean('Have Sent') # Whether to send an authentication code
    manual_sign_id = fields.Many2one('manual.sign',string='Manual Sign')

    @api.multi
    def send_code(self):
        """
        Send a code
        :return:
        """
        # No interface operation
        if self.driver:
            try:
                self.driver.close()
            except:
                pass
            finally:
                SignatureCode.driver = None
        options = Options()
        options.add_argument('--headless')

        # Open the browser, no interface, and don't let selenium generate logs
        driver = selenium.webdriver.Firefox(options=options,service_log_path=os.devnull)

# This step is key, once the property has been generated, we need to use the class
# property modification method to save this property to the class for the next call
        SignatureCode.driver = driver

        self._cr.commit()
        driver.get(self.sign_url)
        time.sleep(15)


        if not self.manual_sign_id.have_got:
            first_confirm_button = driver.find_element_by_xpath("/html/body/div/div/div[10]/div/div[3]/span/button/span")
            first_confirm_button.click()
            self.manual_sign_id.have_got = True
            self._cr.commit()
            time.sleep(2)

        bottom = driver.find_elements_by_xpath("/html/body/div/div/div[2]/div/div[9]/span/img[@class='toBottom']")
        if bottom:
            bottom[0].click()
            time.sleep(3)

        ac1 = driver.find_elements_by_class_name("es-drag-seal")[0]
        ac2 = driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div/div[2]/div/div[5]/div/div/span")
        time.sleep(1)
        ActionChains(driver).drag_and_drop(ac1, ac2).perform()

        time.sleep(2)
        submit_button = driver.find_element_by_xpath("//button//span[text()='submit']")
        submit_button.click()

        time.sleep(3)
        driver.switch_to.frame(0)
        short_message = driver.find_element_by_xpath("//a[text()='sign']")
        short_message.click()

        time.sleep(3)
        send_code = driver.find_element_by_xpath("//div[@class='el-form-item__content']//button//span[text()='get code']")
        send_code.click()
        time.sleep(2)
        self.have_sent = True
        self._cr.commit()
        raise UserError(_('The authentication code has been sent to the phone, please check the receipt'))


    @api.multi
    def confirm_sign_code(self):
        """
        validation code
        :return:
        """
        if not self.have_sent:
            raise UserError(_('Please send the verification code first'))
        if not self.sign_code:
            raise UserError(_('Please fill sign code'))
        sign_code = self.sign_code

        # Since we have previously modified class properties with classes, as long as we
        # don't close the wizard, the class properties that have been changed will not be   
        # released.
        driver = self.driver

        # Enter the verification code
        input_code = driver.find_element_by_xpath("//div[@class='el-input']//input[@class='el-input__inner' and @placeholder='Enter the verification code']")
        input_code.send_keys(sign_code) # Enter the verification code
        time.sleep(2)

        # confirm
        confirm_button = driver.find_element_by_xpath("//p[@class='realname-form-opt']//button//span[text()='confirm']")
        confirm_button.click()
        time.sleep(4)

        # Here you have to judge whether the captcha is correct or not, based on the web
        # domain changes
        fail_tip = driver.find_elements_by_xpath("//div[@class='van-toast van-toast--middle van-toast--fail']")
        if fail_tip: #failed
            fail_msg = driver.find_elements_by_xpath("//div[@class='van-toast__text' and text()='failed']")
            if fail_msg:
                raise UserError(_('Verification code is incorrect, please re-enter'))
            else:
                raise UserError(_('Too many verifications, please review again'))

        # close
        time.sleep(5)
        driver.close()

        return {
            'type':'ir.actions.client',
            'tag':'reload'
        }
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <record id="signature_code_form_view" model="ir.ui.view">
        <field name="name">Signature Code Form View</field>
        <field name="model">signature.code</field>
        <field name="arch" type="xml">
            <form string="Signature Code Form View">
                <sheet>
                    <group>
                        <group>
                            <field name="have_sent" invisible="1"/>
                            <field name="sign_code" readonly="0"/>
                        </group>
                        <group>
                            <button name="send_code" string="Send Code"
                                    attrs="{'invisible':[('have_sent','=',True)]}"
                                    type="object" default_focus="1" class="btn-primary"/>
                        </group>
                    </group>
                </sheet>
                <footer>
                    <button string="Confirm" name="confirm_sign_code" type="object" default_focus="1"
                            class="btn-primary"/>
                    <button string="Cancel" class="btn-default" special="cancel"/>
                </footer>
            </form>
        </field>
    </record>
</odoo>
0 голосов
/ 28 апреля 2020

pychong

В этом методе def handel_web_send_captcha(self) добавлено code точно так же, как

ctx = self.env.context.copy()
ctx.update({'previous_driver': driver})
action = {
    'name': _("Please enter the verification code"),
    'type': 'ir.actions.act_window',
    'res_model': 'signature.code',
    'view_type': 'form',
    'view_mode': 'form',
    'target': 'new',
    'context': ctx,
}

И в этом методе def confirm_sign_code(self), получите данные предыдущего драйвера следующим образом:

driver = self._context.get('previous_driver')
print("\n\n driver ", driver)

Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...