1656873660
En este tutorial, aprenderá a configurar Flask con htmx y Tailwind CSS . El objetivo de htmx y Tailwind es simplificar el desarrollo web moderno para que pueda diseñar y habilitar la interactividad sin abandonar la comodidad y la facilidad de HTML. También veremos cómo usar Flask-Assets para agrupar y minimizar activos estáticos en una aplicación Flask.
htmx es una biblioteca que le permite acceder a funciones de navegador modernas como AJAX, CSS Transitions, WebSockets y Server-Sent Events directamente desde HTML, en lugar de usar JavaScript. Le permite crear interfaces de usuario rápidamente directamente en el marcado.
htmx amplía varias funciones ya integradas en el navegador, como realizar solicitudes HTTP y responder a eventos. Por ejemplo, en lugar de solo poder realizar solicitudes GET y POST a través de elementos a
y form
, puede usar atributos HTML para enviar solicitudes GET, POST, PUT, PATCH o DELETE en cualquier elemento HTML:
<button hx-delete="/user/1">Delete</button>
También puede actualizar partes de una página para crear una aplicación de página única (SPA): enlace CodePen
Abra la pestaña de red en las herramientas de desarrollo del navegador. Cuando se hace clic en el botón, se envía una solicitud XHR al https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode
punto final. Luego, la respuesta se agrega al p
elemento con un id
de salida.
Para obtener más ejemplos, consulte la página de ejemplos de interfaz de usuario de los documentos oficiales de htmx.
Ventajas :
Contras :
Tailwind CSS es un marco CSS de "utilidad primero". En lugar de enviar componentes preconstruidos (en los que se especializan marcos como Bootstrap y Bulma ), proporciona bloques de construcción en forma de clases de utilidad que permiten crear diseños y diseños de forma rápida y sencilla.
Por ejemplo, tome el siguiente HTML y CSS:
<style>
.hello {
height: 5px;
width: 10px;
background: gray;
border-width: 1px;
border-radius: 3px;
padding: 5px;
}
</style>
<div class="hello">Hello World</div>
Esto se puede implementar con Tailwind así:
<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>
Consulte el convertidor CSS Tailwind para convertir CSS sin formato en las clases de utilidad equivalentes en Tailwind. Compara los resultados.
Ventajas :
<div class="bg-white dark:bg-black">
.Contras :
Flask-Assets es una extensión diseñada para administrar activos estáticos en una aplicación Flask. Con él, crea una canalización de activos simple para:
Con eso, ¡veamos cómo trabajar con cada una de las herramientas anteriores en Flask!
Para comenzar, cree un nuevo directorio para nuestro proyecto, cree y active un nuevo entorno virtual e instale Flask junto con Flask-Assets:
$ mkdir flask-htmx-tailwind && cd flask-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$
(venv)$ pip install Flask==2.1.1 Flask-Assets==2.0
A continuación, instalemos pytailwindcss y descarguemos su binario:
(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss
A continuación, agregue un archivo app.py :
# app.py
from flask import Flask
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
Después de importar Bundle y Environment , creamos un nuevo Environment
y registramos nuestros activos CSS a través de un archivo Bundle
.
El paquete que creamos toma src/main.css como entrada, que luego se procesará y enviará a dist/main.css cuando ejecutemos Tailwind CSS CLI.
Dado que todos los archivos estáticos de Flask residen en la carpeta "estática" de forma predeterminada, las carpetas "src" y "dist" mencionadas anteriormente residen en la carpeta "estática".
Con eso, configuremos Tailwind.
Comience creando un archivo de configuración de Tailwind:
(venv)$ tailwindcss init
Este comando creó un archivo tailwind.config.js en la raíz de su proyecto. Todas las personalizaciones relacionadas con Tailwind van a este archivo.
Actualice tailwind.config.js así:
module.exports = {
content: [
'./templates/**/*.html',
],
theme: {
extend: {},
},
plugins: [],
}
Toma nota de la sección de contenido . Aquí configura las rutas a las plantillas HTML de su proyecto. Tailwind CSS escaneará sus plantillas, buscando nombres de clases de Tailwind. El archivo CSS de salida generado solo contendrá CSS para los nombres de clase relevantes que se encuentran en sus archivos de plantilla. Esto ayuda a mantener pequeños los archivos CSS generados, ya que solo contendrán los estilos que realmente se están utilizando.
Agrega lo siguiente a static/src/main.css :
/* static/src/main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Aquí, definimos todas las clases base
, components
y utilities
de Tailwind CSS.
Ahora tiene Flask-Assets y Tailwind conectados. A continuación, veremos cómo publicar un archivo index.html para ver el CSS en acción.
Agregue una ruta junto con un bloque principal para ejecutar el servidor de desarrollo de Flask en app.py de la siguiente manera:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Cree una carpeta de "plantillas". Luego, agregue un archivo base.html :
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Toma nota del {% assets 'css' %}
bloque. Dado que registramos el paquete CSS con el entorno de la aplicación, podemos acceder a él usando el nombre registrado css
, y {{ ASSET_URL }}
automáticamente usará la ruta.
Además, agregamos algo de color al cuerpo HTML a través bg-blue-100
de , que cambia el color de fondo a azul claro.
Agregue el archivo index.html :
<!-- templates/index.html -->
{% extends "base.html" %}
{% block content %}
<h1>Hello World</h1>
{% endblock content %}
Ahora, ejecute el siguiente comando en la raíz del proyecto para escanear las plantillas en busca de clases y generar un archivo CSS:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Debería ver un nuevo directorio llamado "dist" dentro de la carpeta "estática".
Tome nota del archivo static/dist/main.css generado .
Inicie el servidor de desarrollo a través python app.py
de y navegue hasta http://localhost:5000 en su navegador para ver los resultados.
Con Tailwind configurado, agreguemos htmx a la mezcla y construyamos una búsqueda en vivo que muestre los resultados a medida que escribe.
En lugar de obtener la biblioteca htmx de un CDN, descárguemosla y usemos Flask-Assets para agruparla.
Descargue la biblioteca de https://unpkg.com/htmx.org@1.7.0/dist/htmx.js y guárdela en "static/src".
Ahora, para crear un nuevo paquete para nuestros archivos JavaScript, actualice app.py así:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
js = Bundle("src/*.js", output="dist/main.js") # new
assets.register("css", css)
assets.register("js", js) # new
css.build()
js.build() # new
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Aquí, creamos un nuevo paquete llamado js
, que sale a static/dist/main.js . Como no estamos usando ningún filtro aquí, los archivos de origen y de destino serán los mismos.
A continuación, agregue el nuevo activo a nuestro archivo base.html :
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<!-- new -->
{% assets 'js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Para que tengamos algunos datos con los que trabajar, guarde https://github.com/testdrivenio/flask-htmx-tailwind/blob/master/todo.py en un nuevo archivo llamado todo.py.
Agregaremos la capacidad de buscar según el título de cada tarea pendiente.
Actualice el archivo index.html así:
<!-- templates/index.html -->
{% extends 'base.html' %}
{% block content %}
<div class="w-small w-2/3 mx-auto py-10 text-gray-600">
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
<span class="htmx-indicator">Searching...</span>
</div>
<table class="border-collapse w-small w-2/3 mx-auto">
<thead>
<tr>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
</tr>
</thead>
<tbody id="todo-results">
{% include 'todo.html' %}
</tbody>
</table>
{% endblock content %}
Tomemos un momento para ver los atributos definidos desde htmx:
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
/search
punto final.#todo-results
elemento.Agrega el archivo templates/todo.html :
<!-- templates/todo.html -->
{% if todos|length>0 %}
{% for todo in todos %}
<tr class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.id}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.title}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
{% if todo.completed %}
<span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
{% else %}
<span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
Este archivo muestra todos los que coinciden con nuestra consulta de búsqueda.
Finalmente, agregue el controlador de ruta a app.py :
@app.route("/search", methods=["POST"])
def search_todo():
search_term = request.form.get("search")
if not len(search_term):
return render_template("todo.html", todos=[])
res_todos = []
for todo in todos:
if search_term in todo["title"]:
res_todos.append(todo)
return render_template("todo.html", todos=res_todos)
El /search
punto final busca todos y presenta la plantilla todo.html con todos los resultados.
Actualice las importaciones en la parte superior:
from flask import Flask, render_template, request
from flask_assets import Bundle, Environment
from todo import todos
A continuación, actualice el archivo CSS de salida:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Ejecute la aplicación usando python app.py
y navegue hasta http://localhost:5000 nuevamente para probarla:
En este tutorial, vimos cómo:
htmx puede representar elementos sin recargar la página. Lo más importante es que puede lograr esto sin escribir JavaScript. Aunque esto reduce la cantidad de trabajo requerido en el lado del cliente, los datos enviados desde el servidor pueden ser más altos ya que está enviando HTML renderizado.
Ofrecer plantillas HTML parciales como esta fue popular a principios de la década de 2000. htmx proporciona un giro moderno a este enfoque. En general, ofrecer plantillas parciales se está volviendo popular nuevamente debido a la complejidad de los marcos como React y Vue. Puede agregar WebSockets a la mezcla para ofrecer cambios en tiempo real también. Este mismo enfoque es utilizado por el famoso Phoenix LiveView . Puede leer más sobre HTML sobre WebSockets en El futuro del software web es HTML sobre WebSockets y HTML sobre WebSockets .
La biblioteca aún es joven, pero el futuro parece muy prometedor.
Fuente: https://testdriven.io
1656873660
En este tutorial, aprenderá a configurar Flask con htmx y Tailwind CSS . El objetivo de htmx y Tailwind es simplificar el desarrollo web moderno para que pueda diseñar y habilitar la interactividad sin abandonar la comodidad y la facilidad de HTML. También veremos cómo usar Flask-Assets para agrupar y minimizar activos estáticos en una aplicación Flask.
htmx es una biblioteca que le permite acceder a funciones de navegador modernas como AJAX, CSS Transitions, WebSockets y Server-Sent Events directamente desde HTML, en lugar de usar JavaScript. Le permite crear interfaces de usuario rápidamente directamente en el marcado.
htmx amplía varias funciones ya integradas en el navegador, como realizar solicitudes HTTP y responder a eventos. Por ejemplo, en lugar de solo poder realizar solicitudes GET y POST a través de elementos a
y form
, puede usar atributos HTML para enviar solicitudes GET, POST, PUT, PATCH o DELETE en cualquier elemento HTML:
<button hx-delete="/user/1">Delete</button>
También puede actualizar partes de una página para crear una aplicación de página única (SPA): enlace CodePen
Abra la pestaña de red en las herramientas de desarrollo del navegador. Cuando se hace clic en el botón, se envía una solicitud XHR al https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode
punto final. Luego, la respuesta se agrega al p
elemento con un id
de salida.
Para obtener más ejemplos, consulte la página de ejemplos de interfaz de usuario de los documentos oficiales de htmx.
Ventajas :
Contras :
Tailwind CSS es un marco CSS de "utilidad primero". En lugar de enviar componentes preconstruidos (en los que se especializan marcos como Bootstrap y Bulma ), proporciona bloques de construcción en forma de clases de utilidad que permiten crear diseños y diseños de forma rápida y sencilla.
Por ejemplo, tome el siguiente HTML y CSS:
<style>
.hello {
height: 5px;
width: 10px;
background: gray;
border-width: 1px;
border-radius: 3px;
padding: 5px;
}
</style>
<div class="hello">Hello World</div>
Esto se puede implementar con Tailwind así:
<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>
Consulte el convertidor CSS Tailwind para convertir CSS sin formato en las clases de utilidad equivalentes en Tailwind. Compara los resultados.
Ventajas :
<div class="bg-white dark:bg-black">
.Contras :
Flask-Assets es una extensión diseñada para administrar activos estáticos en una aplicación Flask. Con él, crea una canalización de activos simple para:
Con eso, ¡veamos cómo trabajar con cada una de las herramientas anteriores en Flask!
Para comenzar, cree un nuevo directorio para nuestro proyecto, cree y active un nuevo entorno virtual e instale Flask junto con Flask-Assets:
$ mkdir flask-htmx-tailwind && cd flask-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$
(venv)$ pip install Flask==2.1.1 Flask-Assets==2.0
A continuación, instalemos pytailwindcss y descarguemos su binario:
(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss
A continuación, agregue un archivo app.py :
# app.py
from flask import Flask
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
Después de importar Bundle y Environment , creamos un nuevo Environment
y registramos nuestros activos CSS a través de un archivo Bundle
.
El paquete que creamos toma src/main.css como entrada, que luego se procesará y enviará a dist/main.css cuando ejecutemos Tailwind CSS CLI.
Dado que todos los archivos estáticos de Flask residen en la carpeta "estática" de forma predeterminada, las carpetas "src" y "dist" mencionadas anteriormente residen en la carpeta "estática".
Con eso, configuremos Tailwind.
Comience creando un archivo de configuración de Tailwind:
(venv)$ tailwindcss init
Este comando creó un archivo tailwind.config.js en la raíz de su proyecto. Todas las personalizaciones relacionadas con Tailwind van a este archivo.
Actualice tailwind.config.js así:
module.exports = {
content: [
'./templates/**/*.html',
],
theme: {
extend: {},
},
plugins: [],
}
Toma nota de la sección de contenido . Aquí configura las rutas a las plantillas HTML de su proyecto. Tailwind CSS escaneará sus plantillas, buscando nombres de clases de Tailwind. El archivo CSS de salida generado solo contendrá CSS para los nombres de clase relevantes que se encuentran en sus archivos de plantilla. Esto ayuda a mantener pequeños los archivos CSS generados, ya que solo contendrán los estilos que realmente se están utilizando.
Agrega lo siguiente a static/src/main.css :
/* static/src/main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Aquí, definimos todas las clases base
, components
y utilities
de Tailwind CSS.
Ahora tiene Flask-Assets y Tailwind conectados. A continuación, veremos cómo publicar un archivo index.html para ver el CSS en acción.
Agregue una ruta junto con un bloque principal para ejecutar el servidor de desarrollo de Flask en app.py de la siguiente manera:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Cree una carpeta de "plantillas". Luego, agregue un archivo base.html :
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Toma nota del {% assets 'css' %}
bloque. Dado que registramos el paquete CSS con el entorno de la aplicación, podemos acceder a él usando el nombre registrado css
, y {{ ASSET_URL }}
automáticamente usará la ruta.
Además, agregamos algo de color al cuerpo HTML a través bg-blue-100
de , que cambia el color de fondo a azul claro.
Agregue el archivo index.html :
<!-- templates/index.html -->
{% extends "base.html" %}
{% block content %}
<h1>Hello World</h1>
{% endblock content %}
Ahora, ejecute el siguiente comando en la raíz del proyecto para escanear las plantillas en busca de clases y generar un archivo CSS:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Debería ver un nuevo directorio llamado "dist" dentro de la carpeta "estática".
Tome nota del archivo static/dist/main.css generado .
Inicie el servidor de desarrollo a través python app.py
de y navegue hasta http://localhost:5000 en su navegador para ver los resultados.
Con Tailwind configurado, agreguemos htmx a la mezcla y construyamos una búsqueda en vivo que muestre los resultados a medida que escribe.
En lugar de obtener la biblioteca htmx de un CDN, descárguemosla y usemos Flask-Assets para agruparla.
Descargue la biblioteca de https://unpkg.com/htmx.org@1.7.0/dist/htmx.js y guárdela en "static/src".
Ahora, para crear un nuevo paquete para nuestros archivos JavaScript, actualice app.py así:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
js = Bundle("src/*.js", output="dist/main.js") # new
assets.register("css", css)
assets.register("js", js) # new
css.build()
js.build() # new
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Aquí, creamos un nuevo paquete llamado js
, que sale a static/dist/main.js . Como no estamos usando ningún filtro aquí, los archivos de origen y de destino serán los mismos.
A continuación, agregue el nuevo activo a nuestro archivo base.html :
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<!-- new -->
{% assets 'js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Para que tengamos algunos datos con los que trabajar, guarde https://github.com/testdrivenio/flask-htmx-tailwind/blob/master/todo.py en un nuevo archivo llamado todo.py.
Agregaremos la capacidad de buscar según el título de cada tarea pendiente.
Actualice el archivo index.html así:
<!-- templates/index.html -->
{% extends 'base.html' %}
{% block content %}
<div class="w-small w-2/3 mx-auto py-10 text-gray-600">
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
<span class="htmx-indicator">Searching...</span>
</div>
<table class="border-collapse w-small w-2/3 mx-auto">
<thead>
<tr>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
</tr>
</thead>
<tbody id="todo-results">
{% include 'todo.html' %}
</tbody>
</table>
{% endblock content %}
Tomemos un momento para ver los atributos definidos desde htmx:
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
/search
punto final.#todo-results
elemento.Agrega el archivo templates/todo.html :
<!-- templates/todo.html -->
{% if todos|length>0 %}
{% for todo in todos %}
<tr class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.id}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.title}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
{% if todo.completed %}
<span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
{% else %}
<span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
Este archivo muestra todos los que coinciden con nuestra consulta de búsqueda.
Finalmente, agregue el controlador de ruta a app.py :
@app.route("/search", methods=["POST"])
def search_todo():
search_term = request.form.get("search")
if not len(search_term):
return render_template("todo.html", todos=[])
res_todos = []
for todo in todos:
if search_term in todo["title"]:
res_todos.append(todo)
return render_template("todo.html", todos=res_todos)
El /search
punto final busca todos y presenta la plantilla todo.html con todos los resultados.
Actualice las importaciones en la parte superior:
from flask import Flask, render_template, request
from flask_assets import Bundle, Environment
from todo import todos
A continuación, actualice el archivo CSS de salida:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Ejecute la aplicación usando python app.py
y navegue hasta http://localhost:5000 nuevamente para probarla:
En este tutorial, vimos cómo:
htmx puede representar elementos sin recargar la página. Lo más importante es que puede lograr esto sin escribir JavaScript. Aunque esto reduce la cantidad de trabajo requerido en el lado del cliente, los datos enviados desde el servidor pueden ser más altos ya que está enviando HTML renderizado.
Ofrecer plantillas HTML parciales como esta fue popular a principios de la década de 2000. htmx proporciona un giro moderno a este enfoque. En general, ofrecer plantillas parciales se está volviendo popular nuevamente debido a la complejidad de los marcos como React y Vue. Puede agregar WebSockets a la mezcla para ofrecer cambios en tiempo real también. Este mismo enfoque es utilizado por el famoso Phoenix LiveView . Puede leer más sobre HTML sobre WebSockets en El futuro del software web es HTML sobre WebSockets y HTML sobre WebSockets .
La biblioteca aún es joven, pero el futuro parece muy prometedor.
Fuente: https://testdriven.io
1656866280
Neste tutorial, você aprenderá como configurar o Flask com htmx e Tailwind CSS . O objetivo do htmx e do Tailwind é simplificar o desenvolvimento web moderno para que você possa projetar e permitir a interatividade sem nunca deixar o conforto e a facilidade do HTML. Também veremos como usar Flask-Assets para agrupar e reduzir ativos estáticos em um aplicativo Flask.
htmx é uma biblioteca que permite acessar recursos modernos do navegador como AJAX, transições CSS, WebSockets e eventos enviados pelo servidor diretamente do HTML, em vez de usar JavaScript. Ele permite que você construa interfaces de usuário rapidamente diretamente na marcação.
htmx estende vários recursos já embutidos no navegador, como fazer solicitações HTTP e responder a eventos. Por exemplo, em vez de apenas poder fazer solicitações GET e POST por meio a
de elementos e form
, você pode usar atributos HTML para enviar solicitações GET, POST, PUT, PATCH ou DELETE em qualquer elemento HTML:
<button hx-delete="/user/1">Delete</button>
Você também pode atualizar partes de uma página para criar um aplicativo de página única (SPA): link CodePen
Abra a guia de rede nas ferramentas de desenvolvimento do navegador. Quando o botão é clicado, uma solicitação XHR é enviada ao https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode
terminal. A resposta é então anexada ao p
elemento com uma id
saída.
Para obter mais exemplos, confira a página de exemplos de interface do usuário dos documentos htmx oficiais.
Prós :
Contras :
Tailwind CSS é um framework CSS "utilitário em primeiro lugar". Em vez de enviar componentes pré-construídos (nos quais frameworks como Bootstrap e Bulma se especializam), ele fornece blocos de construção na forma de classes de utilitários que permitem criar layouts e designs de maneira rápida e fácil.
Por exemplo, pegue o seguinte HTML e CSS:
<style>
.hello {
height: 5px;
width: 10px;
background: gray;
border-width: 1px;
border-radius: 3px;
padding: 5px;
}
</style>
<div class="hello">Hello World</div>
Isso pode ser implementado com o Tailwind assim:
<div class="h-1 w-2 bg-gray-600 border rounded-sm p-1">Hello World</div>
Confira o CSS Tailwind Converter para converter CSS bruto nas classes de utilitário equivalentes no Tailwind. Compare os resultados.
Prós :
<div class="bg-white dark:bg-black">
.Contras :
Flask-Assets é uma extensão projetada para gerenciar ativos estáticos em um aplicativo Flask. Com ele, você cria um pipeline de ativos simples para:
Com isso, vamos ver como trabalhar com cada uma das ferramentas acima no Flask!
Para começar, crie um novo diretório para nosso projeto, crie e ative um novo ambiente virtual e instale o Flask junto com o Flask-Assets:
$ mkdir flask-htmx-tailwind && cd flask-htmx-tailwind
$ python3.10 -m venv venv
$ source venv/bin/activate
(venv)$
(venv)$ pip install Flask==2.1.1 Flask-Assets==2.0
Em seguida, vamos instalar o pytailwindcss e fazer o download do binário:
(venv)$ pip install pytailwindcss==0.1.4
(venv)$ tailwindcss
Em seguida, adicione um arquivo app.py :
# app.py
from flask import Flask
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
Depois de importar Bundle e Environment , criamos um novo Environment
e registramos nossos ativos CSS nele por meio de um arquivo Bundle
.
O pacote que criamos recebe src/main.css como entrada, que será processada e enviada para dist/main.css quando executarmos a CLI do Tailwind CSS.
Como todos os arquivos estáticos do Flask residem na pasta "static" por padrão, as pastas "src" e "dist" mencionadas acima residem na pasta "static".
Com isso, vamos configurar o Tailwind.
Comece criando um arquivo de configuração do Tailwind:
(venv)$ tailwindcss init
Este comando criou um arquivo tailwind.config.js na raiz do seu projeto. Todas as personalizações relacionadas ao Tailwind vão para este arquivo.
Atualize tailwind.config.js assim:
module.exports = {
content: [
'./templates/**/*.html',
],
theme: {
extend: {},
},
plugins: [],
}
Tome nota da seção de conteúdo . Aqui, você configura os caminhos para os modelos HTML do seu projeto. Tailwind CSS irá escanear seus templates, procurando por nomes de classes Tailwind. O arquivo CSS de saída gerado conterá apenas CSS para os nomes de classe relevantes encontrados em seus arquivos de modelo. Isso ajuda a manter os arquivos CSS gerados pequenos, pois eles conterão apenas os estilos que estão realmente sendo usados.
Adicione o seguinte a static/src/main.css :
/* static/src/main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Aqui, definimos todas as classes base
, components
e utilities
do Tailwind CSS.
Agora você tem Flask-Assets e Tailwind conectados. Em seguida, veremos como servir um arquivo index.html para ver o CSS em ação.
Adicione uma rota junto com um bloco principal para executar o servidor de desenvolvimento Flask para app.py assim:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
assets.register("css", css)
css.build()
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Crie uma pasta "modelos". Em seguida, adicione um arquivo base.html a ele:
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Tome nota do {% assets 'css' %}
bloco. Como registramos o pacote CSS no ambiente do aplicativo, podemos acessá-lo usando o nome registrado css
, e o {{ ASSET_URL }}
usará automaticamente o caminho.
Além disso, adicionamos algumas cores ao corpo do HTML via bg-blue-100
, que altera a cor do plano de fundo para azul claro.
Adicione o arquivo index.html :
<!-- templates/index.html -->
{% extends "base.html" %}
{% block content %}
<h1>Hello World</h1>
{% endblock content %}
Agora, execute o seguinte comando na raiz do projeto para verificar os modelos de classes e gerar um arquivo CSS:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Você deve ver um novo diretório chamado "dist" dentro da pasta "static".
Anote o arquivo static/dist/main.css gerado.
Inicie o servidor de desenvolvimento via python app.py
e navegue até http://localhost:5000 em seu navegador para ver os resultados.
Com o Tailwind configurado, vamos adicionar htmx à mistura e construir uma pesquisa ao vivo que exibe os resultados conforme você digita.
Em vez de buscar a biblioteca htmx de um CDN, vamos baixá-la e usar o Flask-Assets para agrupá-la.
Baixe a biblioteca de https://unpkg.com/htmx.org@1.7.0/dist/htmx.js e salve-a em "static/src".
Agora, para criar um novo pacote para nossos arquivos JavaScript, atualize app.py assim:
# app.py
from flask import Flask, render_template
from flask_assets import Bundle, Environment
app = Flask(__name__)
assets = Environment(app)
css = Bundle("src/main.css", output="dist/main.css")
js = Bundle("src/*.js", output="dist/main.js") # new
assets.register("css", css)
assets.register("js", js) # new
css.build()
js.build() # new
@app.route("/")
def homepage():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
Aqui, criamos um novo pacote chamado js
, que gera static/dist/main.js . Como não estamos usando nenhum filtro aqui, os arquivos de origem e destino serão os mesmos.
Em seguida, adicione o novo ativo ao nosso arquivo base.html :
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% assets 'css' %}
<link rel="stylesheet" href="{{ ASSET_URL }}">
{% endassets %}
<!-- new -->
{% assets 'js' %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
<title>Flask + htmlx + Tailwind CSS</title>
</head>
<body class="bg-blue-100">
{% block content %}
{% endblock content %}
</body>
</html>
Para que tenhamos alguns dados para trabalhar, salve https://github.com/testdrivedio/flask-htmx-tailwind/blob/master/todo.py em um novo arquivo chamado todo.py .
Adicionaremos a capacidade de pesquisar com base no título de cada tarefa.
Atualize o arquivo index.html assim:
<!-- templates/index.html -->
{% extends 'base.html' %}
{% block content %}
<div class="w-small w-2/3 mx-auto py-10 text-gray-600">
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
<span class="htmx-indicator">Searching...</span>
</div>
<table class="border-collapse w-small w-2/3 mx-auto">
<thead>
<tr>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">#</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Title</th>
<th class="p-3 font-bold uppercase bg-gray-200 text-gray-600 border border-gray-300 hidden lg:table-cell">Completed</th>
</tr>
</thead>
<tbody id="todo-results">
{% include 'todo.html' %}
</tbody>
</table>
{% endblock content %}
Vamos dar uma olhada nos atributos definidos de htmx:
<input
type="text"
name="search"
hx-post="/search"
hx-trigger="keyup changed delay:250ms"
hx-indicator=".htmx-indicator"
hx-target="#todo-results"
placeholder="Search"
class="bg-white h-10 px-5 pr-10 rounded-full text-2xl focus:outline-none"
>
/search
terminal.#todo-results
elemento.Adicione o arquivo templates/todo.html :
<!-- templates/todo.html -->
{% if todos|length>0 %}
{% for todo in todos %}
<tr class="bg-white lg:hover:bg-gray-100 flex lg:table-row flex-row lg:flex-row flex-wrap lg:flex-no-wrap mb-10 lg:mb-0">
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.id}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">{{todo.title}}</td>
<td class="w-full lg:w-auto p-3 text-gray-800 text-center border border-b block lg:table-cell relative lg:static">
{% if todo.completed %}
<span class="rounded bg-green-400 py-1 px-3 text-xs font-bold">Yes</span>
{% else %}
<span class="rounded bg-red-400 py-1 px-3 text-xs font-bold">No</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
Este arquivo renderiza os todos que correspondem à nossa consulta de pesquisa.
Por fim, adicione o manipulador de rotas a app.py :
@app.route("/search", methods=["POST"])
def search_todo():
search_term = request.form.get("search")
if not len(search_term):
return render_template("todo.html", todos=[])
res_todos = []
for todo in todos:
if search_term in todo["title"]:
res_todos.append(todo)
return render_template("todo.html", todos=res_todos)
O /search
terminal procura todos e renderiza o modelo todo.html com todos os resultados.
Atualize as importações no topo:
from flask import Flask, render_template, request
from flask_assets import Bundle, Environment
from todo import todos
Em seguida, atualize o arquivo CSS de saída:
(venv)$ tailwindcss -i ./static/src/main.css -o ./static/dist/main.css --minify
Execute o aplicativo usando python app.py
e navegue até http://localhost:5000 novamente para testá-lo:
Neste tutorial, vimos como:
htmx pode renderizar elementos sem recarregar a página. Mais importante, você pode conseguir isso sem escrever nenhum JavaScript. Embora isso reduza a quantidade de trabalho necessária no lado do cliente, os dados enviados do servidor podem ser maiores, pois ele está enviando HTML renderizado.
Servir modelos HTML parciais como esse era popular no início dos anos 2000. htmx fornece um toque moderno a essa abordagem. Em geral, servir templates parciais está se tornando popular novamente devido à complexidade de frameworks como React e Vue. Você pode adicionar WebSockets à mistura para fornecer alterações em tempo real também. Essa mesma abordagem é usada pelo famoso Phoenix LiveView . Você pode ler mais sobre HTML sobre WebSockets em O futuro do software da Web é HTML sobre WebSockets e HTML sobre WebSockets .
A biblioteca ainda é jovem, mas o futuro parece muito brilhante.
Fonte: https://testdrive.io
1596530868
Want to develop a website or re-design using CSS Development?
We build a website and we implemented CSS successfully if you are planning to Hire CSS Developer from HourlyDeveloper.io, We can fill your Page with creative colors and attractive Designs. We provide services in Web Designing, Website Redesigning and etc.
For more details…!!
Consult with our experts:- https://bit.ly/3hUdppS
#hire css developer #css development company #css development services #css development #css developer #css
1602955151
In this tutorial I would like to introduce you to one of the fastest growing and promising CSS Frameworks at the moment, Tailwind CSS. It is different from other frameworks, such as Bootstrap, because it is built on a new way of building user interfaces using a utility-first CSS classes structure, as opposed to the OOCSS structure from other frameworks.
By the end of this guide you will be able to install, configure and build a responsive hero section (live demo) using the utility-first classes from Tailwind CSS and configure the project using the recommended PostCSS powered Tailwind configuration file for better maintainability and versatility.
Here’s the table of contents for this tutorial for Tailwind CSS:
Read the full tutorial from Themesberg.
#tailwind #tailwind-css #tailwind-css-tutorial #tutorial #open-source
1604404836
By reading this article you will browse a list of the most popular plugins and extensions for the utility-first CSS framework, Tailwind CSS. Although the default code base of the framework already covers a lot of the needs when building user interfaces, you can never get enough plugins and extensions powered by the open-source community.
One of the requirements for a plugin to appear on this list is to be open-source with no other strings attached so that the developers browsing this list can stay assured that they can use the plugin for their Tailwind CSS powered project.
Check out the list of Tailwind CSS Plugins and Extensions on Themesberg.
#tailwindcss #tailwind #tailwind-css #tailwind-css-plugins #themesberg