Как передать объект между представлениями в django? - PullRequest
1 голос
/ 19 января 2020

Предыстория / Проблема

У меня есть веб-приложение, которое выполняет различные задания. Одно из этих заданий включает в себя запуск сценария python, который регистрируется в linkedin.

Когда я запускаю сценарий, запускается экземпляр безголового хрома, который переходит на страницу входа в систему и отправляет надлежащие учетные данные. До этого момента все работало нормально, но иногда linkedin отправляет мой запрос на URL контрольной точки и предлагает мне отправить специальный пин-код, отправленный на мою электронную почту, прежде чем я смогу продолжить.

Мне трудно понять, как реализовать эту условную логику c, на мой взгляд; в принципе, я хочу, чтобы я мог ввести пин-код в своем веб-приложении.

Ожидаемый результат

Запустить сценарий из django, чтобы войти в linkedin, и попросите пользователя ввести пин-код, если контрольная точка достигнута, в противном случае продолжайте, если контрольная точка не достигнута и вход был успешным.

То, что я пробовал

  • Google - Не удалось найти ничего, что указывало бы c на мою проблему.

  • Код ниже - На рисунке ниже показана моя текущая попытка. Я знаю, что это можно сделать, но я не уверен, стоит ли мне пытаться создать его в одном представлении или я должен попытаться передать свой экземпляр хрома в другое представление (объекты не сериализуются, поэтому я не уверен как бы я это сделал, может быть, я мог бы передать идентификатор хрома другому экземпляру моего веб-драйвера, но я не думаю, что это лучший метод?)

  • Ajax? - Я на самом деле не пробовал это, но я знаю, что это вариант.

Примечания **

Приведенный ниже код - это все. Но единственная важная часть, которую следует учитывать, - это представление. Я подумал, что добавление остальных может прояснить логику c и помочь кому-нибудь помочь мне. Надеюсь, это не слишком многословно!

Просмотр

def verify_linkedin(request):
    """Used for verifying login to linkedin with email pincode"""
    ln = LinkedinScraper()
    if ln.login_to_linkedin(username=os.getenv("LINKEDIN_USERNAME"), password=os.getenv("LINKEDIN_PASSWORD")):
        return HttpResponse("<h1>You are verified</h1>")
    else:
        if request.method == "POST":
            form = VerifyLinkedinForm(request.POST)
            if form.is_valid():
                print(form.cleaned_data)
                pin_code = form['verification_key']
                ln.authenticate_linkedin_login(pin_code)
                return redirect("home")
        else:
            form = VerifyLinkedinForm()

    context = {"form": form}
    return render(request, "linkedin_verify.html", context)

Форма

class VerifyLinkedinForm(forms.Form):
    verification_key = forms.CharField()
    helper = FormHelper()
    helper.form_method = "post"
    helper.layout = Layout(
        'verification_key',
        FormActions(
            Submit("submit", "Verify Linkedin", style="display: block; margin: auto; margin-bottom:2em;",
                css_class="btn btn-success", ),
        )
    )

Шаблон

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %}

Веб-браузер Backend

class LinkedinScraper(WebScraper):
    """Class for logging into linkedin with chromedriver and scraping linkedin"""

    def __init__(self, headless=True, **kwargs):
        super(LinkedinScraper, self).__init__()
        self.setup_driver(headless=headless)
        self.data = {}
        self.pause = 10
        self.retries = 0
        self.max_retries = 3

    def login_to_linkedin(self, username: str, password: str) -> bool:
        """ Navigates to Linkedin login page and logs in with credentials"""
        login_url = "https://www.linkedin.com/login"
        self.driver.get(login_url)
        user_element = self.driver.find_element("id", "username")
        pass_element = self.driver.find_element("id", "password")
        login_btn = self.driver.find_element_by_class_name(
            "login__form_action_container"
        )
        self.login_and_authenticate(login_btn, user_element, pass_element, username, password)
        if 'checkpoint' in self.driver.current_url:
            return False
        else:
            return True

    def authenticate_linkedin_login(self, pin_code: str):
        """ Sometimes when logging into linkedin from a new ip address, linkedin will flag account for suscipicous access
        If this happens we need to use a pin code sent to email and input it into the form.

        This should be immedidately called after login_and_authenticate returns False
        """
        if 'checkpoint' in self.driver.current_url:
            verification_element = self.driver.find_element_by_xpath("//input[@id='input__email_verification_pin']")
            print(pin_code)
            self.random_send_keys(element=verification_element, keys=pin_code)
            submit_element = self.driver.find_element("id", "email-pin-submit-button")
            submit_element.click()
            return True
        else:
            raise BaseException(f"Driver not on correct url, current url is {self.driver.current_url} -- Should contain checkpoint")

1 Ответ

0 голосов
/ 26 января 2020

Есть два способа решить эту проблему. Одним из способов было создание экземпляра объекта вне представлений, что было немного хакерским и совершенно не масштабируемым, но я смог проверить свою учетную запись электронной почты с помощью селена через веб-браузер. Мне не нужно было передавать объекты между представлениями, потому что они были глобальными.

Второй способ - не использовать селен. Что я и сделал в итоге. Если кто-то заинтересован в таком подходе, оставьте мне сообщение или загляните в pyppeteer.

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