UC02834 · Programação web
Aulify · Componente Tecnológica

Programação web

Backend, HTTP, APIs REST, templates, BD
UC02834 · 50 horas · 4,5 pontos Nível 4 · TDS · Ano 3
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Resultados de aprendizagem

  1. Construir servidor web com framework (Flask/FastAPI).
  2. Implementar rotas, templates e formulários.
  3. Criar API REST com BD.
  4. Aplicar autenticação e segurança.
Junta tudo: HTML/CSS (UC02833), Python (UC00606-08), SQL (UC02830), BD (UC02831), segurança (UC02836).
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Bloco 1 · Como funciona a web

Request → Response

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

O ciclo

Browser  ──── HTTP GET /produtos ────►  Servidor
                                          │
                                     route handler
                                          │
                                     consulta BD
                                          │
                                     renderiza HTML
Browser  ◄──── HTTP 200 + HTML ────────  Servidor

Servidor: recebe request → processa → devolve resposta (HTML, JSON, ficheiro).

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Cliente vs servidor

Frontend (cliente) Backend (servidor)
HTML, CSS, JS Python, Node, PHP, Java
Corre no browser Corre no servidor
Visível ao utilizador Lógica, BD, secrets
UC02833 UC02834 (esta)

O backend nunca confia no frontend — validação sempre no servidor.

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Bloco 2 · Flask

Primeiro servidor

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Hello world

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return "<h1>Olá, Aulify!</h1>"

@app.route("/sobre")
def sobre():
    return "Página sobre"

if __name__ == "__main__":
    app.run(debug=True)

flask runhttp://localhost:5000.

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Rotas e parâmetros

@app.route("/produto/<int:id>")
def produto(id):
    return f"Produto {id}"

@app.route("/pesquisa")
def pesquisa():
    termo = request.args.get("q", "")
    return f"A pesquisar: {termo}"
    # /pesquisa?q=python

@app.route("/criar", methods=["GET", "POST"])
def criar():
    if request.method == "POST":
        nome = request.form["nome"]
        # guardar...
    return render_template("form.html")
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Templates Jinja2

@app.route("/produtos")
def produtos():
    lista = [{"nome": "Caneta", "preco": 1.5}]
    return render_template("produtos.html", produtos=lista)
<!-- templates/produtos.html -->
<ul>
{% for p in produtos %}
  <li>{{ p.nome }} — {{ p.preco }}€</li>
{% endfor %}
</ul>

{{ }} escapa automaticamente (anti-XSS). {% %} para lógica.

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Herança de templates

<!-- base.html -->
<!DOCTYPE html>
<html><head><title>{% block titulo %}{% endblock %}</title></head>
<body>
  {% block conteudo %}{% endblock %}
</body></html>
<!-- pagina.html -->
{% extends "base.html" %}
{% block titulo %}Produtos{% endblock %}
{% block conteudo %}
  <h1>Lista</h1>
{% endblock %}

DRY: layout comum num só sítio.

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Bloco 3 · API REST

Dados, não HTML

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

REST · princípios

Método Acção Exemplo
GET Ler GET /api/produtos
POST Criar POST /api/produtos
PUT Substituir PUT /api/produtos/5
PATCH Modificar PATCH /api/produtos/5
DELETE Apagar DELETE /api/produtos/5

Recursos no plural, sem verbos na URL (/produtos não /getProdutos).

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

API com Flask

from flask import jsonify, request

@app.route("/api/produtos")
def listar():
    return jsonify(produtos)

@app.route("/api/produtos/<int:id>")
def get(id):
    p = next((x for x in produtos if x["id"] == id), None)
    if p is None:
        return jsonify({"erro": "não encontrado"}), 404
    return jsonify(p)

@app.route("/api/produtos", methods=["POST"])
def criar():
    dados = request.get_json()
    # validar...
    return jsonify(novo), 201
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

FastAPI · alternativa moderna

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Produto(BaseModel):
    nome: str
    preco: float

@app.get("/produtos")
def listar() -> list[Produto]:
    return produtos

@app.post("/produtos", status_code=201)
def criar(p: Produto):
    produtos.append(p)
    return p

Validação automática + docs OpenAPI em /docs.

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Bloco 4 · BD e autenticação

Persistir e proteger

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Ligar à BD (SQLAlchemy)

from flask_sqlalchemy import SQLAlchemy

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
db = SQLAlchemy(app)

class Produto(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    nome = db.Column(db.String(150), nullable=False)
    preco = db.Column(db.Float)

@app.route("/produtos")
def listar():
    produtos = Produto.query.all()
    return render_template("lista.html", produtos=produtos)
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Autenticação

from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import login_user, login_required, current_user

# Registo
hash = generate_password_hash(senha)  # nunca texto plano

# Login
if check_password_hash(user.pwd_hash, senha):
    login_user(user)

# Proteger rota
@app.route("/painel")
@login_required
def painel():
    return f"Olá {current_user.nome}"
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Segurança essencial

  • Hash de senhas (bcrypt/werkzeug), nunca texto plano.
  • ORM / prepared statements — sem SQL injection.
  • Jinja2 auto-escape — sem XSS.
  • CSRF token em formulários (Flask-WTF).
  • HTTPS sempre em produção.
  • Validação no servidor — frontend não é de confiança.
  • Secrets em variáveis de ambiente.
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Bloco 5 · Deploy

Pôr online

Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Estrutura de projecto

app/
├── app.py            # entry point
├── models.py         # modelos BD
├── routes/           # blueprints
├── templates/        # Jinja2
├── static/           # CSS, JS, imagens
├── requirements.txt
├── .env              # secrets (gitignore)
└── .gitignore
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web

Deploy

  • Render / Railway / Fly.io — fácil, plano grátis.
  • Vercel (serverless) — bom para FastAPI/Next.
  • VPS (DigitalOcean, Hetzner) + Gunicorn + Nginx.
  • Sempre: gunicorn (não flask run) em produção, DEBUG=False, secrets em env.
gunicorn app:app --workers 4 --bind 0.0.0.0:8000
Aulify · Componente Tecnológica · Cursos Profissionais
UC02834 · Programação web
Aulify · UC02834 · Fim

Do request ao response, com tudo no meio.

📧 geral@aulify.pt
Aulify · Componente Tecnológica · Cursos Profissionais