Резюме: Jyserver позволяет доступ к JavaScript и DOM непосредственно из Python и позволяет JavaScript вызовать и получать доступ к Python. Он работает без проблем с колбой и другими рамками.
Например, используя Jyserver, сервер, управляющий Python, может сделать это:
self.js.document.getElementById("act").innerHTML = "Jump"
И он автоматически преобразует выражение в JavaScript, отправляет его в браузер и выполнит его, что приведет к обновлению страницы. Это также может работать наоборот, как в этом HML Snip:
Когда кнопка нажата, Increment ()
выполняется на сервере. Не требуется дополнительного кода. Структура предоставляет библиотеку, которая делает это возможным.
Традиционно веб -фреймворки Python, такие как Flask или Django, являются сложным взаимодействием HTML, CCS, JavaScript и Python. Каждое обновление страницы включает в себя некоторые HTML, некоторые JavaScript, параметры маршалирования, асинхронную связь с сервером, некоторые хруст в Python и поездку обратно в JavaScript. Или некоторые вариации на это.
Похоже, что много работы, если вы просто хотите создать простой фронт для приложения.
Но Что, если вся эта сложность была скрыта, а синтаксис языка динамически обеспечил сантехнику?
Пример будет освещен. Допустим, ваша страница очень проста. Вы хотите создать счетчик и кнопку, чтобы увеличить количество. Вы хотите, чтобы все управлялось сервером. Ваш index.html
Файл будет выглядеть так:
0
Вашему серверу нужно изменить текст для счет
и ответьте на Increment ()
Анкет Используя Jyserver, ваш код сервера будет выглядеть так для Flask:
from flask import Flask, render_template, request app = Flask(__name__) import jyserver.Flask as jsf @jsf.use(app) class App: def __init__(self): self.count = 0 def increment(self): self.count += 1 self.js.document.getElementById("count").innerHTML = self.count @app.route('/') def index_page(): return App.render(render_template('flask-simple.html'))
В бутылке это будет код:
from bottle import route, run import jyserver.Bottle as jsb import time @jsb.use class App: def __init__(self): self.count = 0 def increment(self): self.count += 1 self.js.document.getElementById("count").innerHTML = self.count @route('/') def index(): return App.render(file='flask-simple.html') run(host='localhost', port=8080)
Это весь код, который вам нужен. @jsf.use (app)
Подключает класс приложений с вашим объектом приложения Flask приложение
. @jsb.use
делает то же самое для бутылки. Когда браузер откроется “/”, страница будет отображаться как index_page ()
Анкет App.render ()
добавит соответствующий JavaScript. Когда кнопка нажимается в браузере, она вызывает server.increment ()
, что вызывает App.increment ()
Выполнить на сервере, который затем изменяет DOM в режиме реального времени, обновляя innerhtml
для счет
Анкет
Одним из основных преимуществ этого подхода является то, что он позволяет легко поместить логику программы в одном месте. Если вы хотите, чтобы сервер контролировал вещи, вы используете self.js
объект, чтобы изменить DOM и выполнить операторы в браузере. С другой стороны, если вы хотите контролировать все от клиента, вы можете написать логику в JavaScript и использовать сервер
объект для выполнения конкретных команд или переменных запросов на сервере.
Как это достигнуто? Секретный соус в сервер
объект в браузере и self.js
объект в Python.
Это то, что происходит за кулисами.
После начала сервер будет прослушать новые HTTP -запросы и пересылать специальные запросы на специальные сообщения в
Жизервер. Колба
модуль. Это достигается строкой@jsf.use (app)
АнкетКогда запрашивается “/”, Jyserver будет читать
Flask-Simple.html
и вставьте специальный код JavaScript в HTML, который позволяет общаться, прежде чем отправлять его в браузер. Этот код создаетсервер
Прокси -объект.Этот инъекционный код приведет к тому, что браузер отправит асинхронный HTTP -запрос на сервер с просьбой выполнить новые команды для выполнения браузера. Затем он ждет ответа на заднем плане. Это используется для передачи команд с сервера в браузер.
Когда пользователь нажимает на кнопку
B1
,сервер
Прокси -объект называется. Он извлечет имя метода-в этом случаеприращение
-И затем сделайте HTTP-запрос на сервер для выполнения этого оператора.Сервер получит этот HTTP -запрос, посмотрите на класс приложения, найдите метод с этим именем и выполните его.
Выполненный метод
Increment ()
Сначала увеличивает переменнуюсчитать
. Затем он начинает создавать команду JavaScript, используя специальноеself.js
командованиеself.js
использует динамические языковые функции Python__getAttr__
,__setattr__
и т. д. для создания синтаксиса JavaScript на лету.Когда это «динамическое» оператор получит значение (в нашем случае
self.count
), оно будет преобразовано в JavaScript и отправляется в браузер, который ждал новых команд на шаге 3. Заявление будет выглядеть как:document.getElementById ("count"). innerhtml
Браузер получит оператор, оценит его и вернет результаты на сервер. Затем браузер запросит новые команды в фоновом режиме.
Это кажется сложным, но этот процесс обычно занимает менее 0,01 секунды. Если для выполнения есть несколько операторов, они сдаются в очередь и обрабатываются вместе, что отступает на болтовне.
Как типично в веб -приложениях, все общение инициируется браузером, обычно асинхронно. Сервер держит очередь ожидающих команд и соответствует результатам по мере их возврата.
Исключением из асинхронных запросов является то, что браузер инициирует вызов сервера. В этом случае, если блоков нет, браузер ждет ответа сервера, когда выполнение будет завершено. Часто это ожидание не требуется, но оно используется, чтобы сделать поток более предсказуемым и избежать выполнения вне порядка.
В системе есть три основные части.
HTTP Server; в таком случае Фляжка
JavaScript “сантехника” и объект сервера
Python “сантехника” и self.js объект
Модуль Jyserver должен быть настроен для ответа на запросы публикации на страницу “/_process_srv0”. Все общение происходит через этот URL.
сервер
Объект живет в браузере и используется JavaScript для выполнения команд на сервере. В основном, сервер
Объект является прокси для клиентского приложения. Он может вызывать методы, значения запроса и установить значения. Например, следующий код позвонит reset ()
на сервере для каждого клика.
Кроме того, возможна настройка значения на клиентском объекте сервера:
Вы также можете запускать методы и получить возвратные значения.
alert(server.getresult(125, 99))
self.js
объект
Код Python использует self.js
объект для общения с браузером. Допустим, у вас есть функция в JavaScript в браузере.
var factor = 1.3 function adjust(value) { return value * factor; }
Это можно запустить со стороны сервера Python, используя:
result = self.js.adjust(i) print("Factor is", self.js.factor, "2 x result is", 2 * result)
Чтобы изменить значения, просто установите их в код.
self.js.factor = 2.3 self.js.data = {"a":15.4, "b":12.7, "c":[5,4,6]}
Последнее утверждение будет преобразовать структуру в словарь JavaScript. Это преобразование данных осуществляется через json
Модуль в Python и Json
модуль в JavaScript.
Просто чтобы сделать жизнь еще проще, self.js
У объекта есть специальная сокращение для запроса элементов с помощью ID, используя ключевое слово дом
. Эти два утверждения одинаковы:
self.js.document.getElementById("count").innerHTML = 10 self.js.dom.count.innerHTML = 10
Чтобы проиллюстрировать еще несколько функций, мы создадим приложение для секунды. Проект состоит в том, чтобы запустить функцию на сервере, которая время от времени обновляет время на HTML -странице. Мы также предоставляем две кнопки: одна для сброса в ноль, а другие, чтобы приостановить обновления.
WHEN
Класс должен будет определить методы сброса () и Stop (). Просто для ударов, мы будем динамически изменять обратный вызов паузы.
from flask import Flask, render_template, request app = Flask(__name__) import jyserver.Flask as jsf import time @jsf.use(app) def reset(self): self.start0 = time.time() self.js.dom.time.innerHTML = "{:.1f}".format(0) def stop(self): self.running = False self.js.dom.b2.innerHTML = "Restart" self.js.dom.b2.onclick = self.restart def restart(self): self.running = True self.js.dom.b2.innerHTML = "Pause" self.js.dom.b2.onclick = self.stop
Обратите внимание, что когда вы нажимаете Stop, Stop ()
Метод вызывается, который меняет текст, а затем изменяет Onclick
обратный вызов кнопки. Следующий щелчок будет запускать перезапуск ()
, который затем изменит текст и обратный вызов.
Далее нам нужен Главный
функция, которая выполняется для каждого нового сеанса. В нашем случае программа работает за 1000 итераций, а затем завершается. Когда это заканчивается, сервер также отключится. Естественно, вы можете преобразовать это в бесконечный цикл, и программа никогда не прекратится. Или, если функция опущена, то сервер просто слушает подключения на неопределенный срок.
@jsf.task def main(self): self.running = True self.start0 = time.time() for i in range(1000): if self.running: t = "{:.1f}".format(time.time() - self.start0) self.js.dom.time.innerHTML = t time.sleep(.1)
Наконец, мы запускаем сервер для обработки запросов страниц.
@app.route('/') def index_page(name=None): App.main() return App.render(render_template('clock.html'))
Jyserver доступен в PIP или Conda.
pip install jyserver
Исходный код найден в GitHub Repository gyserver
ftrias/geserver
Web Framework Jyserver с синтаксисом Pythonic JavaScript
Поскольку Целью Gyserver состоит в том, чтобы упростить создание веб-фронта для приложений и киосков. Сантехника для подключения к фреймворку проста.
Хотя сам jyserver – это составляющие, «клей», необходимый для подключения к такими структурами, как колба или Джанго, нет. По сути, вам нужно только перенаправить запрос “/_process_srv0”. Это весь код “клея”, который соединяет Jyserver to Flask:
from flask import Flask, request import json import jyserver import threading def task(func): def wrapper(*args): server_thread = threading.Thread(target=func, args=args, daemon=True) server_thread.start() return wrapper def use(flaskapp): def decorator(appClass): global context context = jyserver.ClientContext(appClass) @flaskapp.route('/_process_srv0', methods=['GET', 'POST']) def process(): if request.method == 'POST': req = json.loads(request.data) result = context.processCommand(req) if result is None: return '' return result else: return "GET reqeust not allowed" return context return decorator
Как видите, довольно просто подключить его к любой другой структуре.
Об авторе
Fernando “Fen” Trias – серийный предприниматель, генеральный директор Vindor Music и Avid Python и C ++ Coder, специализирующийся на науке о данных, встраиваемом развитии и кибербезопасности в Бостонских районах. Он является автором, Pyembedc, Pyembedc, TeensyThReads и другими проектами с открытым исходным кодом.
Оригинал: “https://dev.to/ftrias/access-js-dom-from-flask-app-using-jyserver-23h9”