Per què fem servir Python i Flask?
Cal entendre la diferència entre una web estàtica i una de dinàmica.
· Web estàtica (Htlm i CSS): La informació és fixa i només es pot llegir, no es pot modificar ni guardar dades ni interactuar amb la base de dades.
· Web dinàmica (Python i Flask): El Python actua com el Backend
- Connexió amb Base de Dades: Python ens permet connectar la web amb MySQL per guardar registres, llegir dades i generar informes en temps real.
- Processament de dades: Ens permet fer que la web “faci coses”, com validar un formulari, gestionar sessions d’usuari (login) i escalar l’aplicació a mesura que creix.
- Gestió de rutes: Python decideix què mostrar a l’usuari en funció de les seves accions, enviant dades de la base de dades directament a la interfície.
El prompt que vaig utilitzar per generar el codi Python amb la IA, per fer el registre de la LAN Party, va ser el següent:
Vull que em facis un formulari de registre per a la LAN Party de l’Institut Castellbisbal amb codi Python. El formulari ha de ser en català i ha de preguntar el nom, cognoms, el “nickname”, telèfon, correu electrònic, dies d’assistència (10, 11 i 12 d’abril), DNI/NIE i si hi ha alguna intolerància. Vull que el formulari s’obri en una pestanya nova del Firefox en el Localhost:5000. Vull que es guardin els registres en la base de dades i si tanco l’aplicació que les dades es quedin guardades.
Vull que els colors siguin contrastants perquè hi sigui visible i estètic.
El codi que em va generar va ser el següent:
import webbrowser
import threading
import os
from flask import Flask, render_template_string, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 1. Configuració de la Base de Dades (Es crea al mateix directori)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'lan_party.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 2. Model de dades per als registres
class Participant(db.Model):
id = db.Column(db.Integer, primary_key=True)
nom = db.Column(db.String(100))
nickname = db.Column(db.String(50))
dni = db.Column(db.String(20))
telefon = db.Column(db.String(20))
email = db.Column(db.String(100))
dies = db.Column(db.String(100))
intolerancies = db.Column(db.String(200))
# Crear la base de dades
with app.app_context():
db.create_all()
# 3. Plantilla HTML i CSS integrada (Disseny d'alt contrast)
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LAN Party - Inst. Castellbisbal</title>
<style>
:root {
--neon-cyan: #00f2ff;
--bg-dark: #0a0a0a;
--card-bg: #161616;
--text-white: #ffffff;
}
body {
background-color: var(--bg-dark);
color: var(--text-white);
font-family: 'Segoe UI', Roboto, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.form-container {
background-color: var(--card-bg);
padding: 40px;
border-radius: 20px;
border: 3px solid var(--neon-cyan);
box-shadow: 0 0 25px rgba(0, 242, 255, 0.3);
width: 100%;
max-width: 450px;
}
h1 { color: var(--neon-cyan); text-align: center; font-size: 24px; text-transform: uppercase; letter-spacing: 2px; }
label { display: block; margin-top: 15px; font-weight: bold; color: var(--neon-cyan); }
input, textarea {
width: 100%;
padding: 12px;
margin-top: 5px;
border-radius: 8px;
border: 1px solid #333;
background-color: #222;
color: white;
box-sizing: border-box;
font-size: 16px;
}
input:focus { outline: none; border-color: var(--neon-cyan); box-shadow: 0 0 10px rgba(0, 242, 255, 0.5); }
.checkbox-group { display: flex; justify-content: space-between; padding: 10px 0; }
.checkbox-item { display: flex; align-items: center; gap: 5px; cursor: pointer; }
button {
width: 100%;
padding: 15px;
margin-top: 30px;
background-color: var(--neon-cyan);
color: #000;
border: none;
border-radius: 10px;
font-weight: bold;
cursor: pointer;
font-size: 18px;
transition: 0.3s;
}
button:hover { background-color: #00b8c4; transform: scale(1.02); }
.success { color: #00ff88; text-align: center; }
</style>
</head>
<body>
<div class="form-container">
<h1>LAN Party 2026</h1>
<p style="text-align:center; font-size: 0.9em; opacity: 0.8;">Institut Castellbisbal</p>
{% if success %}
<div class="success">
<h2>✓ Registre Completat!</h2>
<p>Ens veiem el 10 d'abril.</p>
<a href="/" style="color: var(--neon-cyan);">Torna enrere</a>
</div>
{% else %}
<form method="POST">
<label>Nom i Cognoms</label>
<input type="text" name="nom" placeholder="Nom complet" required>
<label>Nickname</label>
<input type="text" name="nickname" placeholder="El teu àlies de combat" required>
<label>DNI / NIE</label>
<input type="text" name="dni" required>
<label>Telèfon</label>
<input type="tel" name="telefon" required>
<label>Correu Electrònic</label>
<input type="email" name="email" required>
<label>Dies d'assistència (Abril)</label>
<div class="checkbox-group">
<label class="checkbox-item"><input type="checkbox" name="dies" value="10"> 10</label>
<label class="checkbox-item"><input type="checkbox" name="dies" value="11"> 11</label>
<label class="checkbox-item"><input type="checkbox" name="dies" value="12"> 12</label>
</div>
<label>Intoleràncies / Al·lèrgies</label>
<textarea name="intolerancies" placeholder="Escriu 'Cap' si no en tens"></textarea>
<button type="submit">REGISTRAR-ME</button>
</form>
{% endif %}
</div>
</body>
</html>
"""
# 4. Rutes de Flask
@app.route('/', methods=['GET', 'POST'])
def index():
success = False
if request.method == 'POST':
nou_participant = Participant(
nom=request.form.get('nom'),
nickname=request.form.get('nickname'),
dni=request.form.get('dni'),
telefon=request.form.get('telefon'),
email=request.form.get('email'),
dies=", ".join(request.form.getlist('dies')),
intolerancies=request.form.get('intolerancies')
)
db.session.add(nou_participant)
db.session.commit()
success = True
return render_template_string(HTML_TEMPLATE, success=success)
# 5. Funció per obrir Firefox automàticament
def open_firefox():
url = "http://127.0.0.1:5000"
try:
# Intenta obrir específicament Firefox
webbrowser.get('firefox').open_new_tab(url)
except:
# Si no troba la ruta de Firefox, obre el navegador per defecte
webbrowser.open_new_tab(url)
if __name__ == '__main__':
# Obrir navegador després d'1 segon per donar temps al servidor
threading.Timer(1.5, open_firefox).start()
app.run(port=5000, debug=False)
I el formulari que va generar va ser el següent:

