El puente entre Python y ReactUn búho es un nano marco que se puede integrar en otros marcos.
Imagen de sova.online, en la que se ejecutan 3 servidores http:
http://sova.online/ - solo Falcon
http://sova.online:8000/ - solo Django
http://sova.online:8001/ - solo Python (inicio de sesión: 1, contraseña: 1)
Hay códigos fuente e instrucciones de instalación. No hay publicidad allí.

La idea de crear sitios en Python con renderizado en React no es nueva. Hay un marco maravilloso
https://plot.ly/products/dash/ , ¿por qué hacer algo más?
Explique: Owl no está diseñado para el desarrollo de sitios web. Esta es una herramienta para reemplazar clientes gruesos con aplicaciones que se ejecutan a través del navegador (aplicaciones de escritorio).
- ¿Qué es un cliente web?
- No Este no es un cliente web. Esta es una aplicación de navegador.
"No entiendo".
- Desafortunadamente, muchos desarrolladores no entienden.
Como general, trabajé activamente con varias aplicaciones de Internet.
Cliente en línea del banco Ugra (el banco está cerrado).Era una buena aplicación, pero era un applet de Java, es decir. cliente grueso lanzado desde el navegador. Y el banco de Ugra, y applets en el pasado.
Cliente en línea del banco VTB-24 (el banco está cerrado).Soy humanista, pero después de trabajar con este milagro, comenzaron a aparecer pensamientos crueles como: "Hacer que el desarrollador registre 1000 cheques de pago".
Además, como cliente web, es hermoso. La animación se abre en un teléfono móvil. Wow! Genial!
Le pregunté a un amigo contador: ¿cómo trabajas con él?
Ella dice: genial! Cargo los datos en 1s, en 1s trabajo, vuelvo a subir los resultados.
Cliente en línea de SberbankCliente satisfactorio, puedes trabajar. Cuando me pidieron que lo calificara, le di 3 puntos de 5 y le di una lista de comentarios. Esto es con mis 10 pagos por mes. Es probable que quienes hacen 100 facturas al día carguen información.
Llenar un pago.

El área verde, que ocupa el 20% de la pantalla, es el menú. No solo interfiere (posición: fija), dice que el desarrollador no es un profesional. Si comencé a crear un pago, la pantalla debería ser. 3 botones: "Crear", "Guardar como plantilla", "Cancelar". Estos botones son (por alguna razón a continuación). Este no es un SPA de varias páginas: si hace clic en el elemento del menú, se perderán los datos del formulario.
Quien hizo esto ni siquiera entenderá cuál es el golpe: "Normalmente hecho, todos lo hacen, como una biblioteca, la gente trabaja ...". Y él tiene razón. Debe pedirle al gerente del proyecto, y para el gerente, lo principal son las bases de datos y las capas en el modelo conceptual. Y formas: contrataremos niños, dibujarán. Y probablemente estén orgullosos de este truco.
Pisos comerciales (5 piezas, 44 leyes federales)Estas son realmente aplicaciones (no clientes web). Pero no me gustan los controladores de campo.
Ejemplos:

Es extraño alineado, el ancho del campo es claramente insuficiente, no hay altura automática en el campo de entrada.
Otro ejemplo. No hay una plantilla dd.mm.aaaa en el campo "Fecha de publicación", el calendario tiene un error, el icono del calendario da miedo:

Lista en rts-tender: hay una entrada actual resaltada en color, las flechas pueden moverse por la lista, pero no hay desplazamiento automático (puede huir del borde de la pantalla), ni Enter ni la barra espaciadora abren el enlace, la pestaña no está adjunta al registro actual. Aunque solo puede abrir el enlace con el mouse, califico el control con un signo más. Dicha funcionalidad (recordar y resaltar el documento actual) no es suficiente para mí en mail.ru
Parecen pequeñas cosas. Pero la aplicación profesional difiere de la semiprofesional en detalles. Al usuario final no le importa qué base de datos tiene y cuántas capas en el modelo conceptual. Funciona con formularios de pantalla y tiene 3 requisitos: funcional, conveniente, rápido.
Desafortunadamente, la elección del sistema está determinada por los especialistas de TI y los jefes que ellos mismos no trabajaron con el sistema y no lo harán. Apreciarán la velocidad, apreciarán la funcionalidad tal como la entienden, y no les importa la conveniencia, lo más importante, de ser bellas.
Pavel Valeryevich Durov no inventó ni una red social ni un mensajero. Hizo lo que los usuarios necesitaban, de manera conveniente y hermosa. Y la gente aprecia esto, incluso financieramente.
Owl es una herramienta para construir una interfaz profesional.
¿Qué significa esto, por ejemplo, EDMS?
Hay un EDMS, tiene 3 grupos de usuarios:
Superiores
Especialistas en preparación de documentos
Empleados de oficina.
Jefes, son como niños. Necesitan ser simples y hermosos. Idealmente 1 botón y 1 campo. Y para presumir un poco más. Un cliente web y, por supuesto, un cliente móvil para presumir.
Especialistas Cliente web, cross social network / mailer. No olvide que hay muchos especialistas y que necesitan ser entrenados. Cuanto más familiar sea el ambiente para ellos, mejor. El cliente móvil también será útil si el servicio de seguridad lo permite.
Empleados de oficina. Aquí es donde el búho es útil. Los empleados de oficina son un grupo de usuarios formadores de sistemas. Todos los demás pueden enfermarse / irse de vacaciones / dejar de usarlo: el EDMS funcionará. Si el registro se detiene, todo estará listo.
El trabajo administrativo es un transportador, y aquí todo es importante, cualquier pequeña cosa: fuentes, medios tonos, relleno automático, comprobación de valores, facilidad de entrada, etc.
EDS "Caso". Las oficinas de los artistas intérpretes o ejecutantes se realizan en el cliente web, la oficina es un cliente gordo. Todo está bien, pero funcionará hasta que el gobierno prohíba Windows a las agencias gubernamentales. Me encanta Win 7, pero si yo fuera el gobernante, el mercado del mercado se fortalecía con nuevos pedidos, y MS permanecía en la memoria brillante. Por cierto, el 6 de diciembre, Anton Siluanov firmó una
directiva sobre la transición al software doméstico.
Sova.onlineCómo un búho abre un formulario.
Sin varias páginas.
El elemento central del Búho es el componente Documento. Al presionar ctrl-U en la página de inicio, verá todo lo que necesita para crear un objeto de la clase Documento:
- campos de datos de la base de datos;
- url del formulario para mostrar;
- dbAlias, unid - para trabajar con la base de datos;
- Algo más allí.
Hasta cierto punto, el documento es un análogo de la forma Redux.
El formulario se carga como una cadena JSON, luego el diccionario anterior se convierte en un objeto que tiene estilo, className y una matriz (lista) de elementos. La matriz se insertará en el elemento con id = root en el formulario
<div style className>……</div>
Los elementos de matriz son objetos que describen etiquetas.
<div>, <a>, <img>, <button>
, o una matriz, o componentes.
La función de boxeo es responsable de analizar la matriz. Si se encuentra un elemento que contiene una matriz, se llamará recursivamente.
El ombligo de la tierra es, por supuesto, un div.
En el caso más simple, esta es una línea: dict (div = 'Hola', className = 'h2')
Pero puede haber una matriz (matriz de matrices):
def style(**par): return {'style': {**par}} dict(
Hay 3 paneles (cada uno en un archivo separado: subFormTop.py, etc.).
subFormTop.panel () devuelve una matriz para construir el panel superior.
subFormLeft.panel () y subFormRight.panel () se combinan en una cadena ('className': 'row') y describen los paneles izquierdo y derecho.
subFormDown.panel () está comentado (no es útil).
Puede parecer complicado Pero esto es Python: todo se puede simplificar.
Un ejemplo de un formulario de la revista "Informes". La función labField (label, DB_field_name) devuelve una matriz de dos diccionarios (fila de tabla): el primer diccionario es {'div': label}, el segundo {'field': [DB_field_name, 'tx']}.
div = [ docTitle(''), dict ( wl='40mm', className='cellbg-green', div=_table( labField('', 'nodafd'), labField(' ', '_STARTINGTIME'), labField('', '_ENDTIME'), labField('', 'CREATOR'), labField('', 'REPORTCAT'), labField('', 'REPORTNAME'), labField('', 'REPORTTITLE'), labField(' ', 'dt1'), labField(' ', 'dt2'), labField(' 2', 'dt3'), labField(' 2', 'dt4'), labField('', 'LBYEARS'), labField('', 'GRGROUP'), labField(' ', 'QUERYMAIN'), labField('', 'NOTES'), )), sent(), ]

Ejemplos de sova / api / forms / home / top.py (comenzando en sova.online):
diccionario de python
{'a': 'React v16', 'href': 'https://reactjs.org'}
Genera un componente React claro
<a href={'https://reactjs.org'}>React v16</a>
Img es más inteligente que el estándar: en los accesorios puede especificar href y target:
Python:
dict (img = 'imagen? react.ico', estilo = {'ancho': 16}, href = 'https: //reactjs.org')
Un fragmento de un analizador que convierte una matriz de objetos en componentes (boxing.js):
if ( td.img ) {
Escriba en el motor de búsqueda "biblioteca de componentes de reacción". El resultado es predecible, mucho. Pero toda esta abundancia es para sitios web, no para aplicaciones:
Smart-textarea es quizás el único control que me convenía.
React-select: simplificó y rehizo la lista desplegable
Selector de datos / calendario: no encontré nada adecuado. Él escribió el suyo, tomando el G.Chrome incorporado como muestra.
Carga / descarga: nada adecuado, escribió el mío.
Imho: los sitios web tienen un futuro triste. La gran mayoría de los usuarios en el futuro cercano dejarán de usar navegadores (o ya se detuvieron). El teléfono crecerá junto con la tableta, y 1 pizca de 10 aplicaciones satisfará completamente las necesidades.
Ya me he encontrado con programadores dos veces que no saben cómo escribir una dirección de correo electrónico correctamente. ¿Por qué deberían recordar lo que no usan? El mundo esta cambiando.
En Owl, los controladores no son perfectos, pero fueron diseñados para el operador, no para el usuario de la web.
Como ejemplo, el formulario "Marca de transferencia". Una forma bastante universal, utilizada donde hay un jefe. Los campos que controlan la ocultación se encierran en rojo en la captura de pantalla. Las resoluciones adicionales se abren automáticamente a medida que se llenan, si en la parte operativa hay varias instrucciones para diferentes grupos de artistas con diferentes términos. Dos términos por grupo: 1er término al 1er ejecutante, 2do término a los co-ejecutores.

Puedes tocar el formulario
AQUÍUn controlador es un componente React asociado con un campo de base de datos.
Una descripción detallada de los controladores con la capacidad de verificar su funcionamiento se encuentra en Sova.online.
Presta atención a los tipos rtf y json. Rtf se muestra como texto, pero si el texto {_ {objeto} _} aparece en el texto, Owl ejecutará json.parse para esta construcción y agregará el resultado al formulario. Un campo de tipo json debe almacenar una descripción de la matriz de elementos de marcado: [{ele1}, {ele2}, ...]. json.parse se ejecuta antes de renderizar.
Los campos con estos tipos le permiten almacenar marcas en la base de datos o en archivos. Útil para informar y escribir documentación.
La lista de controladores para todos los tipos de campos (controllers.js):
export const controller = prop => { switch (prop.type) {
Una aplicación requiere un mecanismo para manipular controladores.
En un búho, todos los controladores de documentos se almacenan en una variable de documento.
este registro
No me atreví a usar referencias debido a los rumores de que el personal editorial lo cancelaría.
El controlador puede tener las siguientes interfaces:
getValue (param)
setValue (valor, parámetro)
setFocus ()
changeDropList ()
Para acceder al campo deseado, hay métodos de documento
getField (fieldName, param)
setField (fieldName, value, param)
changeDropList (fieldName, param)
setFocus (fieldName)
Para los campos de tipo FileShow, hay un método fileShow ['FILES1 _']. HasAtt (), donde FILES1_ es el nombre del área del archivo. Devuelve verdadero si hay archivos adjuntos. En la marca de transferencia de dichas áreas 2.
Los controladores pueden generar un evento de recalc. Si se registra un controlador para este campo, se ejecutará. Los controladores se encuentran en archivos js cargables.
Un ejemplo y una descripción algo simplificada:
Hay un formulario "Marca de transferencia" (o.py). Contiene el archivo o.js cargado
En o.js los controladores están registrados
recalc: { PROJECTO: doc => doc.forceUpdate(), WHOPRJ2: doc => doc.forceUpdate(), WHOPRJ3: doc => doc.forceUpdate(), … }
, y también se prescriben condiciones de ocultación (proyecto, op, prj1, prj2 ... prj5: esta es la propiedad "nombre" en la descripción de divs):
hide: { project: doc => !doc.getField('projectO'),
Cómo funciona: el campo PROJECTO es una casilla de verificación, cuando se cambia el valor, el controlador genera un evento recalc, el documento llama al manejador recalc.PROJECTO (este).
El controlador simplemente llama a forceUpdate () para volver a dibujar el documento.
Al volver a dibujar, se verifica si el componente en los accesorios tiene un nombre, si hay una función hide [props.name] para este nombre y si devolverá verdadero.
prj3: doc =>! doc.getField ('projectO') || (! doc.getField ('whoPrj2') &&! doc.getField ('whoPrj3'))
Oculte la tercera resolución (área con props.name === 'prj3') si la casilla de verificación 'projectO' está desactivada o los ejecutores no se ingresan en los campos de resolución 2 y 3 (los campos 'whoPrj2' y 'whoPrj3' están vacíos).
El nombre del campo cuando se llaman funciones no distingue entre mayúsculas y minúsculas.
WHOPRJ2 es un cuadro combinado; cuando selecciona un valor, el controlador también generará un evento recalc, que también causará un redibujo. Al elegir un artista en la segunda resolución, abrirá la tercera.
En los archivos js cargados puedes:
- gestionar el escondite;
- gestionar solo la lectura;
- responder a los cambios de campo;
- ejecutar comandos de botones;
- hacer validación de campos y formularios antes de guardar;
Descargue el archivo para el formulario 'fo':
window.sovaActions = window.sovaActions || {}; window.sovaActions.fo = {
Validación de campos: una función que devuelve vacía si todo está bien o un mensaje sobre lo que está mal. Un búho se centrará en un campo no válido.
Validación del formulario - Promesa. En el ejemplo, no hay comprobaciones (sí, siempre se llama), solo se hace algo antes de enviar al servidor.
En forma de reducción, la validación se realiza mediante trow, algún tipo de desenfreno.
Para aquellos que no están familiarizados con las promesas, un ejemplo de lo más simple: const confirmDlg = msg => new Promise((ok, cancel) => confirm(msg) ? ok(' ') : cancel(' cancel')); confirmDlg(' ') .then( s => console.log(s)) .catch( s => console.log(s));
La clase Document tiene varios comandos predefinidos que se pueden usar en botones:
editar: cambiar al modo de edición de formulario
guardar: guardar formulario
cerrar: cierra el formulario
saveClose: guarda y cierra el formulario
prn: imprime un formulario con la opción de una plantilla para imprimir
docOpen: documento abierto
dbOpen: abrir registro
xopen: abrir url
newDoc: crea un nuevo documento con el formulario deseado
La API de forma Redux es más rica, en Owl solo lo necesario.
Múltiples páginas.La clase Document crea un objeto (formulario) que está incrustado en un elemento.
<div id="root"></div>
.
Lo llamaremos el "documento raíz". Si agrega un elemento al documento raíz
<div style = {{position: 'absolute', zIndex: 999}} />, también puede insertar otro objeto Document en él.
¿Qué hacer con los controladores de comandos cargables? Es simple: cada formulario tiene su propio controlador (su propio js), y el documento raíz debe cargar los que puedan ser necesarios.
Ejemplo para la página de inicio sova.online (home.py)
El formulario home.py, para demostrar la naturaleza de varias páginas, abre documentos con los formularios "rkckg", "outlet", "outlet.gru", "o".
Para que todos los formularios funcionen correctamente, debe registrar los scripts para estos formularios en home.py:
javaScriptUrl = ['jsv?api/forms/rkckg/rkckg.js', 'jsv?api/forms/outlet_gru/outlet_gru.js', 'jsv?api/forms/outlet/outlet.js', 'jsv?api/forms/o/o.js', 'jsv?api/forms/home/home.js']
Como al llamar a cualquier función del controlador, el primer parámetro pasa el enlace al documento, las acciones se realizarán con el documento deseado.
OOP y sin milagros.
Reaccionar - no reaccionar
Ya he descrito el formulario de informe. Se abre desde el administrador de informes (flecha "Reaccionar") y describe los parámetros para recopilar el informe.

Los informes en sí mismos (flecha "no reaccionar") se almacenan en documentos subordinados con el formulario "informe" en forma de archivos adjuntos html. Nos involucramos en el desarrollo de informes cuando React no estaba allí, el formulario de "informe" resultó ser simple (20 líneas de html y 15 líneas just-js), ¿por qué cambiar lo que funciona durante 8 años?
Abrir el Administrador de informes.El formulario de informe consta de 4 botones y un iframe. El búho antes de abrir el documento reemplaza src = "" con la línea de URL para descargar el archivo adjunto html en el iframe, el navegador hace el resto.
Los botones EXCEL / WORD son similares: inserte los botones de URL para descargar con el nombre de archivo "report.html.xls" o "report.html.doc" y el tipo mime correspondiente en el lugar correcto. El resto lo hace Excel / Word ("estos animales inteligentes entienden perfectamente todo lo que quieren de ellos").
Desde do_get.py:
downloadUrl = '/download/' + fn + '?' + '&'.join([d.db.alias, d.unid, idbl, fsName, fzip, ctype, flen]) excel = '/download/%s.xls?%s' % (fn, '&'.join([d.db.alias, d.unid, idbl, fsName, fzip, 'application/x-excel', flen])) word = '/download/%s.doc?%s' % (fn, '&'.join([d.db.alias, d.unid, idbl, fsName, fzip, 'application/msword', flen])) html = html.replace('src=""', 'src="%s"' % downloadUrl).replace('openExcel', excel).replace('openWord', word)
Al abrir html en Excel / Word, existen diferencias con el navegador, pero son pequeñas. Y el artículo no trata sobre eso.
Haz una forma desde cero.Datos de origen:
Hay 3 funciones
def snd (* msg, cat = 'snd'):
def err (* msg, cat = 'todos'):
def dbg (* msg, cat = 'snd'):
, que se distribuyen de manera más o menos uniforme en todo el código y escriben mensajes de error y otra basura en el archivo de registro.
El formato del mensaje se pasa al registro. Formatee como:
'% (tiempo de actividad) s% (nombre de nivel) s [% (nombre) s]% (mensaje) s'
El archivo está lleno de mensajes.
...
02/09/2018 17:50:07 DEPURACIÓN [http-server] addr ('127.0.0.1', 49964), “GET / arm HTTP / 1.1” 200 -
09/02/2018 17:54:07 INFO [Espacio libre] Los archivos adjuntos se guardan en ". \ DB \ files" Gratis 68557 Mb
02/09/2018 17:58:07 ERROR [do_get.py] getScript: [Errno 2] No existe ese archivo o directorio: 'sova / api / forms / o / oo.js'
...
Fecha-hora, luego nivel, luego entre corchetes una categoría dentro del nivel, luego un mensaje.
Desafío:
Haga una página para ver el archivo de registro. Que tipo

Llamaremos al formulario "lm", estará formado por la función de página en el módulo api / forms / lm.py
def page(dbAlias, mode, userName, multiPage): return dict( style(background='url(/image?bg51.jpg)', backgroundSize='100% 100%'), div=[ dict( style(width='200px', float='left', background='rgba(210,218,203, 0.5)', padding='0 5px'), div=[ _field('type', 'list', [' |all', '|err', '|info', '|debug'], saveAlias=1, **style(margin='10px auto', width=170, height=110) ), _field('cat', 'list', 'TYPE_ALIAS|||api.get?loadDropList&logger|keys_{FIELD}', listItemClassName='repName', listItemSelClassName='repNameSel', **style(height='calc(100vh - 133px)', overflow='auto') ) ], ), _field('msg', 'fd', br=1, **style(overflow='auto', height='100vh', font='bold 12px Courier', background='rgba(255,255,255, 0.8)') ), ] )
En el lado izquierdo hay 2 campos, ambos con el tipo de lista: tipo y gato (tipo y categoría de mensaje).
A la derecha hay un campo de mensaje de tipo fd (forDisplayOnly).
Los tipos de mensajes se escriben en la descripción del campo (['Todos los registros | todos', 'Errores | err', ...),
xhr extrae las categorías del diccionario global con una llamada url complicada:
api.get? loadDropList & logger | keys_err devolverá en formato json una matriz (lista) de categorías del diccionario global. Algo así como bien ('logger', 'keys_err').
Los mensajes se generan cuando la función queryOpen abre un documento en lm.py
def queryOpen(d, mode, ground): logParser() ls = well('logger_all', 'AL L') s = '\n'.join(reversed(ls)) d.msg = s d.type_alias = 'all'
logParser lee y analiza el archivo de registro. Descompone los resultados en varios arreglos y los guarda en el diccionario global. Nada interesante: 2 re simples e iterador loop.
Funciones para trabajar con el diccionario global:
toWell (o, clave1, [clave2]): guarde el objeto "o" en el diccionario global
bien (clave1, [clave2]): tome un objeto del diccionario global por clave (por dos claves).
Esto es suficiente para el primer dibujo. Para poder mostrar mensajes del tipo y categoría deseados, es necesario hacer js cargables.
En lm.py agrega la línea
javaScriptUrl = 'jsv? api / forms / lm / lm.js'
y crea lm.js:
window.sovaActions = window.sovaActions || {}; window.sovaActions.lm = {
getLogData extrae mensajes del servidor del tipo y categoría deseados:
def getLogData(par, un): lg, _, cat = par.partition('|') msg = well('logger_' + lg, cat) return 200, 'text/html; charset=UTF-8', '\n'.join(reversed(msg))
Puedes disfrutar del formulario
AQUÍ .
Inicialmente, el registro se realizó en base al módulo de registro estándar
usando logging.FileHandler, .addHandler y otros getLogger y setFormatter.
Cómo enseñar Pero al mismo tiempo estaba con errores. Puedes tirar piedras, pero cuando tiré el registro y comencé a escribir en un archivo, el código se hizo más corto, más comprensible y los fallos desaparecieron.
Se incluye un servidor wsgi multiproceso autoescrito con autorización Digest. Esto no es para sitios. ¿Por qué era necesario en absoluto?
El cliente tiene 40 jur. personas, en la mayoría de los casos, 1-2-3 personas trabajan con el sistema. Se prohíbe almacenar datos en Internet. Todos ganan 7. Requiere facilidad de instalación y configuración.
Solución: utilizando cx-Freeze e Inno Setup, creamos el instalador, lo ejecutamos en la computadora más responsable y obtenemos un servidor mini-http para la red local, comenzando como un servicio de Windows. Nada mas. No puede usar el wsgiref.simple_server incorporado o el wsgi_Werkzeug integrado en Python, porque son de un solo subproceso: mientras una solicitud falla, otras esperarán.
Es poco probable que sorprenda a alguien al informar que el Django WSGIServer / 0.2 CPython / 3.5.3 incorporado es varias veces más rápido que el Python auto-escrito. Solo que esto no importa: los formularios y directorios se almacenan en caché en el cliente, solo los datos de la base de datos se transmiten muy rápidamente a través de la red local.
Hay una razón más: la aplicación de escritorio tiene acceso a los recursos de la computadora (firma digital, archivos, escáner ...). Para obtener el mismo acceso desde el navegador, debe escribir un complemento o colgar un pequeño servidor http en los servicios, que puede oler desde el servidor principal y realizar las acciones necesarias en el área local.
El búho no usa las herramientas de marco para trabajar con la base de datos. En el directorio dbToolkit, algo similar en estructura a MongoDB (o Lotus Notes) en SQLite3:
Clase de libro - db (en terminología de MongoDB y Lotus Notes)
Class DocumentCollection - una colección de documentos del Libro
La clase de documento es un documento (un objeto que contiene cualquier número de campos).
Instalación:Descargar
owl.zip desde sova.online
El archivo contiene el directorio de Owl, desde el cual puede ejecutar Owl desde django, falcon o sin frameworks.
Descargar, descomprimir
Instalar Python3 (3.5+)
1. búho - sin marcos. Atencion Inicio de sesión: 1, Contraseña: 1
Linux:
cd ./owl
python3 wsgi_sova.py
o en una ventana separada
pantalla -Udm python3 wsgi_server.py
Ventanas:
cd ./owl
wsgi_sova.py
2. Django
Linux:
Instala django:
pip3 instalar django
cd ./owl
python3 manage.py runserver
o en una ventana separada
pantalla -Udm python3 manage.py runserver 127.0.0.1:8000
Ventanas:
Instala django:
pip install django
cd ./owl
manage.py runserver
3. halcón
Linux:
pip3 instalar falcon
cd ./owl
python3 wsgi_sova.py falconApp: api 8001 log_falcon / falcon
Ventanas:
pip install falcon
cd ./owl
wsgi_sova.py falconApp: api 8001 log_falcon / falcon
**********************
- el título del artículo es extraño, ¿entendiste qué es "SPA de varias páginas"?
- estratagema de marketing normal
- ¿Por qué sin Redux? Todos usan Redux.
- No me gusta la palabra "reductor"
- pero en serio? ombineReducers en cualquier nivel de la jerarquía ... Es tan hermoso
Es una página múltiple, bebé. Los controladores de comandos deben estar dentro del formulario y no como cuernos de venado
- ¿Por qué incluso escribiste un artículo?
- PR