Рубрики
Без рубрики

Графический интерфейс для Python с использованием React и распределен с PIP

Джанго врач анализирует кодовые базы и предлагает улучшения. Раньше это был только SaaS, но сегодня мы Tagged с Django, Python, WebDev, React.

Джанго врач анализирует кодовые базы и предлагает улучшения. Раньше это был только SaaS, но сегодня мы выпустили его как автономный инструмент командной строки. В этом сообщении объясняется, как мы использовали React, чтобы сделать хороший пользовательский интерфейс для нашего интерфейса командной строки Python:

Для нашего инструмента командной строки мы хотели хороший пользовательский интерфейс. Мы используем React для нашего веб -сайта, поэтому мы рассмотрели, как передавать данные из Python, чтобы отреагировать и обратно, таким образом, чтобы его можно было легко распределить через PIP установить django-doctor Анкет Мы не использовали Django или Flask, так как хотели яблоко, а не горилла, держащее яблоко.

Следующий компонент React – это мастер форм, который принимает список элементов и позволяет пользователю выбирать подмножество, тогда эта подмножество элементов размещается на сервере:

// App.jsx
export default function({ messages }) {
  const [httpState, setHttpState] = React.useState({
    isInProgress: false,
    isComplete: false,
  })

  function handleSave(selectedMessages) {
    setHttpState({isInProgress: true, isComplete: false })
    fetch('/done/', {
      method: "POST",
      headers: {"Content-Type": "application/json"},
      body: JSON.stringify(selectedMessages)
    }).then(result => {
      setHttpState({isInProgress: false, isComplete: true })
    }).catch(result => {
      setHttpState({isInProgress: false, isComplete: false })
    })
  }
  if (httpState.isComplete) {
    return 
  } else {
  return (
    
}

Мы можем передать в компонент некоторые данные, предоставленные сценарием Python, выполнив следующее:

// index.js
import React from 'react';
import { render } from "react-dom";

import './App.css';
import './App.jsx';


const contextElement = document.getElementById('context-messages')
const messages = JSON.parse(contextElement.textContent)
render(, rootElement);

Так index.js Ожидает, что HTML -страница, от которой она обслуживается, чтобы содержать элемент с id контекст-месс Чтобы содержать несколько сериализованных данных JSON. Теперь, где входит Python. Мы обслуживаем файл HTML, используя функции, предоставленные Build Python в Wsgiref библиотека:

# wsgi.py

import json
import mimetypes
import pathlib
import threading
from wsgiref.simple_server import make_server
from wsgiref.util import FileWrapper

# a folder containing the built React app, which we trick python into working with by adding an __init__.py to it
import django_doctor.wizard


static_dir = pathlib.Path(django_doctor.wizard.__path__[0])

with open(static_dir / 'index.html', 'r') as f:
    home_template_body = f.read()


def home_handler(environ, respond, app):
    # exposing data to the HTML template using an approach inspired by https://docs.djangoproject.com/en/3.1/ref/templates/builtins/#json-script
    messages = json.dumps(app.messages)
    body = home_template_body.replace(
        '',
        f''
    )
    body = response_body.encode('utf-8')
    respond('200 OK', [('Content-Type', 'text/html'), ('Content-Length', str(len(body)))])
    return [body]


def static_handler(environ, respond, app):
    # serve the css/js/png/etc files
    content_type = mimetypes.guess_type(environ['PATH_INFO'])[0]
    path = static_dir / environ['PATH_INFO'][1:]
    respond('200 OK', [('Content-Type', content_type)])
    return FileWrapper(open(path, "rb"))


def submit_handler(environ, respond, app):
    body_size = int(environ.get('CONTENT_LENGTH', 0))
    request_body = environ['wsgi.input'].read(body_size)
    selected_messages = json.loads(request_body)
    # TODO: do something with selected_messages
    respond('200 OK', [('Content-Type', 'text/plain')])
    # make the server kill itself after the response is sent
    threading.Timer(0.5, app.server.shutdown).start()
    return [b'']


class Application:
    def __init__(self, messages):
        self.messages = messages

    def __call__(self, environ, respond):
        if environ.get('PATH_INFO') == '/':
            return home_handler(environ=environ, respond=respond, app=self)
        elif environ.get('PATH_INFO') == '/done/':
            return submit_handler(environ=environ, respond=respond, app=self)
        elif environ.get('PATH_INFO').startwith('/static/'):
            return static_handler(environ=environ, respond=respond)



def create(messages):
    app = Application(messages=messages)
    server = make_server(host='localhost', port='9000', app=app)
    app.server = server
    return server

Тогда мы можем создать какой -нибудь инструмент командной строки, который вызывает wsgi.create :

import argparse

from django_doctor import check_codebase, wsgi


parser = argparse.ArgumentParser(prog='Django Doctor')

parser.add_argument('-d', '--directory', default='.')


def handle(argv=sys.argv[1:]):
    options = parser.parse_args(argv)
    messages = check_codebase(project_root=options.directory)
    wsgi.create(messages=messages)

Итак, теперь мы имеем двунаправленную связь с React и Python:

  1. Сценарий командной строки Python, который работает check_codebase затем проходит Сообщения к приложению WSGI
  2. Приложение WSGI, которое отдает HTML -файл, содержащий Сообщения и (не показано) a <Скрипт> тег, который служит настройке, реагирует JS
  3. Приложение React, которое увлажняет JSON, а затем передает его, чтобы сформировать мастер, а затем в конечном итоге публикует выбранные элементы обратно в /выполнено/ Анкет
  4. обработчик wsgi, который видит данные, размещенные в/сделано/что -то с ним делает

Довольно круто. Чтобы сделать его прохладным, мы можем заменить запрос HTTP POST и рендеринг HTML на WebSocket. Менее хакерский. Может быть, мы в конечном итоге будем использовать это в Джанго Доктор Анкет

setup.py Отлично подходит для распространения файлов Python, но для этого нам нужно сделать Setup.py создать распределение, содержащее файлы Python и .js и .png и .html и т. д.

Мы делаем это, копировав приложение Build React в ./волшебник , добавить __init__.py к этому, затем напишите setup.py вот так:

setup(
    name="django_doctor",
    url="https://django.doctor",
    packages=find_packages(include=['django_doctor.wizard',]),
    include_package_data=True,
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Environment :: Web Environment",
        "Framework :: Django",
        "Intended Audience :: Developers",
        "Natural Language :: English",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Topic :: Software Development :: Libraries :: Python Modules",
    ],
)

Мясо в Пакеты – Убедитесь, что мастер Пакет включен, и include_package_data чтобы убедиться, что не Python -файлы тоже распределены.

У вашей кодовой базы Django есть место для улучшения?

Используйте наш инструмент интерфейса командной строки, чтобы проверить. PIP установить Django-Doctor Тогда django_doctor fix Анкет

Оригинал: “https://dev.to/djangodoctor/gui-for-python-using-react-and-distributed-with-pip-1e1b”