MEu voo
Meu ip é 201.81.52.233
Olá! Com certeza. "Veen" é como muitas pessoas pronunciam venv
, que é a ferramenta padrão do Python para criar ambientes virtuais. Usar um venv
é uma das melhores práticas na programação Python, e no Linux Mint é bem simples de fazer.
Vou te guiar passo a passo.
O que é um venv
e por que usar?
Imagine que cada projeto que você cria é uma casa. Cada casa precisa de suas próprias ferramentas (bibliotecas).
Projeto A (uma aplicação web) precisa da ferramenta
Flask
na versão2.0
.Projeto B (um script de análise de dados) precisa da ferramenta
Pandas
e doFlask
na versão3.0
.
Se você instalar todas as ferramentas "soltas" no seu sistema operacional, logo terá um conflito: qual versão do Flask
usar? A 2.0
ou a 3.0
?
O venv
resolve isso criando uma "bolha" ou uma "caixa de ferramentas" isolada para cada projeto. Assim, as ferramentas do Projeto A não interferem nas do Projeto B.
Vantagens:
Organização: Cada projeto tem suas próprias dependências.
Evitar Conflitos: Versões diferentes de uma mesma biblioteca podem coexistir em projetos diferentes.
Reprodutibilidade: Você pode facilmente gerar uma lista de todas as ferramentas usadas (
requirements.txt
) e recriar o ambiente em outro computador.Não "sujar" o sistema: Você mantém a instalação principal do Python do seu Linux Mint limpa.
Passo a Passo para Criar e Usar um venv
no Linux Mint
Passo 1: Abra o Terminal
A forma mais fácil é usar o atalho: Ctrl + Alt + T
.
Passo 2: Garanta que o venv
está instalado
O Python 3 já vem com o Linux Mint, mas o módulo específico do venv
às vezes precisa ser instalado separadamente. É um pacote chamado python3-venv
.
Rode o comando abaixo para atualizar a lista de pacotes e instalar o venv
:
sudo apt update && sudo apt install python3-venv -y
sudo
: Executa o comando como superusuário (administrador).apt update
: Atualiza a lista de pacotes disponíveis.apt install python3-venv
: Instala o pacote dovenv
.-y
: Responde "sim" automaticamente para a instalação.
Passo 3: Crie a Pasta do seu Projeto
É uma boa prática criar o ambiente virtual dentro da pasta do projeto ao qual ele pertence.
# Cria uma nova pasta chamada 'meu_projeto_python'
mkdir meu_projeto_python
# Entra na pasta recém-criada
cd meu_projeto_python
Passo 4: Crie o Ambiente Virtual
Agora, dentro da pasta do seu projeto, use o seguinte comando para criar o ambiente:
python3 -m venv venv
Vamos entender o comando:
python3
: Chama o interpretador Python 3.-m venv
: Diz ao Python para executar o módulovenv
.venv
(o último): É o nome da pasta que será criada para guardar seu ambiente virtual. Usarvenv
como nome é uma convenção muito comum e recomendada.
Após rodar o comando, se você listar os arquivos (ls
), verá uma nova pasta chamada venv
.
usuario@mint:~/meu_projeto_python$ ls
venv
Passo 5: Ative o Ambiente Virtual
Criar o ambiente não o ativa. Para "entrar na bolha", você precisa ativá-lo com o seguinte comando:
source venv/bin/activate
Você saberá que funcionou porque o seu prompt do terminal mudará, mostrando o nome do ambiente entre parênteses.
Antes:
usuario@mint:~/meu_projeto_python$
Depois:
(venv) usuario@mint:~/meu_projeto_python$
Esse (venv)
indica que seu ambiente virtual está ativo.
Passo 6: Use o Ambiente
Com o ambiente ativo, você pode instalar bibliotecas usando pip
. Elas serão instaladas apenas dentro desta "bolha".
Por exemplo, para instalar a biblioteca requests
:
(venv) usuario@mint:~/meu_projeto_python$ pip install requests
Para ver o que está instalado apenas neste ambiente:
(venv) usuario@mint:~/meu_projeto_python$ pip list
Passo 7: Desative o Ambiente
Quando terminar de trabalhar no seu projeto, você pode "sair da bolha" digitando simplesmente:
(venv) usuario@mint:~/meu_projeto_python$ deactivate
O prompt do terminal voltará ao normal, sem o (venv)
.
Resumo Rápido (Comandos Essenciais)
# 1. Instalar o pacote (só na primeira vez)
sudo apt update && sudo apt install python3-venv -y
# 2. Criar pasta do projeto e entrar nela
mkdir meu_projeto
cd meu_projeto
# 3. Criar o ambiente virtual
python3 -m venv venv
# 4. Ativar o ambiente
source venv/bin/activate
# 5. Trabalhar e instalar pacotes (exemplo)
pip install flask
# ... seu código aqui ...
# 6. Desativar quando terminar
deactivate
Dica Extra: Gerenciando Dependências com requirements.txt
Depois de instalar todas as bibliotecas que seu projeto precisa, você pode criar um "arquivo de receita" para que outras pessoas (ou você mesmo no futuro) possam recriar o ambiente facilmente.
Com o ambiente ativo, gere o arquivo:
Bashpip freeze > requirements.txt
Isso cria um arquivo
requirements.txt
com a lista de pacotes e suas versões exatas.Para instalar tudo a partir desse arquivo em um novo ambiente, o comando é:
Bashpip install -r requirements.txt
Pronto! Agora você sabe como gerenciar seus projetos Python de forma profissional no Linux Mint.
Olá, Warley! Entendi perfeitamente. Você quer transformar o script simples que gera um banco de dados em uma aplicação web completa e interativa, com acesso pela rede, sistema de usuários, segurança 2FA, e a capacidade de interagir com os voos.
Este é um passo grande e muito interessante! Para fazer tudo isso, não podemos usar apenas um script. Precisamos construir uma aplicação web. A ferramenta ideal para isso em Python é um "framework web". Vou usar o Flask, que é muito poderoso e flexível.
Vou reestruturar todo o código para criar essa aplicação. O projeto será dividido em partes:
Configuração do Banco de Dados: Um script para criar as novas tabelas (usuários, tickets) e popular os voos.
Aplicação Web Principal (Flask): O cérebro do projeto, que cuidará da lógica, das páginas, do login, etc.
Templates HTML: Os arquivos que definem a aparência do site no navegador.
Vamos abordar cada um dos seus pedidos.
Passo 1: Estrutura do Projeto
Primeiro, organize seus arquivos na seguinte estrutura de pastas:
/meu_projeto_voos/
|
|-- database_setup.py # Script para criar e popular o banco de dados (só roda 1 vez)
|-- app.py # A aplicação web principal (Flask)
|
|-- /templates/
| |-- base.html # Template base para todas as páginas
| |-- login.html # Página de login
| |-- register.html # Página de registro de novo usuário
| |-- setup_2fa.html # Página para configurar o 2FA com QR Code
| |-- index.html # Página principal para ver e filtrar os voos
| |-- view_tickets.html # Página para ver os tickets criados
Passo 2: Instalar as Bibliotecas Necessárias
Você precisará instalar o Flask e outras bibliotecas para lidar com login, 2FA e QR Codes. Abra seu terminal e rode o comando:
pip install Flask Flask-Login Werkzeug pyotp qrcode[pil]
Passo 3: O Código
Agora, vamos criar cada arquivo.
1. database_setup.py
(Script de Preparação do Banco de Dados)
Este script prepara o voos_db.sqlite
com as novas tabelas de usuarios
e tickets
, além de preencher com os voos. Você só precisa rodar este script uma única vez.
# database_setup.py
import sqlite3
import random
from datetime import datetime, timedelta
from werkzeug.security import generate_password_hash
print("Iniciando a configuração do banco de dados...")
db_file = 'voos_db.sqlite'
conn = sqlite3.connect(db_file)
cursor = conn.cursor()
# --- Tabela de Usuários ---
# Armazena o 'secret' do 2FA para cada usuário.
cursor.execute('''
CREATE TABLE IF NOT EXISTS usuarios (
id INTEGER PRIMARY KEY AUTOINCREMENT,
usuario TEXT UNIQUE NOT NULL,
senha_hash TEXT NOT NULL,
otp_secret TEXT
)
''')
print("Tabela 'usuarios' criada ou já existente.")
# --- Tabela de Voos (semelhante à anterior) ---
cursor.execute('''
CREATE TABLE IF NOT EXISTS voos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
numero_voo TEXT NOT NULL,
companhia_aerea TEXT NOT NULL,
origem TEXT NOT NULL,
destino TEXT NOT NULL,
partida DATETIME NOT NULL,
chegada DATETIME NOT NULL,
status TEXT NOT NULL
)
''')
print("Tabela 'voos' criada ou já existente.")
# --- Tabela de Tickets ---
# Vincula um usuário a um voo e armazena a nota/comentário.
cursor.execute('''
CREATE TABLE IF NOT EXISTS tickets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
protocolo TEXT UNIQUE NOT NULL,
id_usuario INTEGER,
id_voo INTEGER,
nota TEXT,
data_criacao DATETIME,
FOREIGN KEY (id_usuario) REFERENCES usuarios (id),
FOREIGN KEY (id_voo) REFERENCES voos (id)
)
''')
print("Tabela 'tickets' criada ou já existente.")
# --- Populando a Tabela de Voos (se estiver vazia) ---
cursor.execute("SELECT COUNT(*) FROM voos")
if cursor.fetchone()[0] == 0:
print("Populando a tabela 'voos' com dados fictícios...")
AIRPORTS = {
'BR': ['GRU', 'GIG', 'BSB', 'CNF', 'SDU'],
'USA': ['JFK', 'LAX', 'MIA', 'ORD', 'ATL'],
'UK': ['LHR', 'LGW', 'MAN', 'EDI', 'STN']
}
AIRLINES = {
'BR': [('GOL', 'G3'), ('LATAM', 'LA')],
'USA': [('American Airlines', 'AA'), ('Delta', 'DL')],
'UK': [('British Airways', 'BA'), ('Virgin Atlantic', 'VS')]
}
STATUS_CHOICES = ['No Horário', 'Atrasado', 'Cancelado']
today = datetime.now()
for day_offset in range(15):
current_date = today + timedelta(days=day_offset)
for _ in range(20): # Gerando 20 voos por dia
paises = list(AIRPORTS.keys())
origem_pais = random.choice(paises)
paises_destino = [p for p in paises if p != origem_pais]
destino_pais = random.choice(paises_destino)
origem_aeroporto = random.choice(AIRPORTS[origem_pais])
destino_aeroporto = random.choice(AIRPORTS[destino_pais])
companhia_nome, companhia_cod = random.choice(AIRLINES[origem_pais])
numero_voo = f"{companhia_cod}{random.randint(1000, 9999)}"
partida_dt = current_date.replace(hour=random.randint(0, 23), minute=random.choice([0, 15, 30, 45]))
chegada_dt = partida_dt + timedelta(hours=random.randint(8, 12), minutes=random.randint(0, 59))
status_voo = random.choices(STATUS_CHOICES, weights=[0.8, 0.15, 0.05], k=1)[0]
cursor.execute(
"INSERT INTO voos (numero_voo, companhia_aerea, origem, destino, partida, chegada, status) VALUES (?, ?, ?, ?, ?, ?, ?)",
(numero_voo, companhia_nome, origem_aeroporto, destino_aeroporto, partida_dt, chegada_dt, status_voo)
)
print("Tabela 'voos' populada.")
else:
print("Tabela 'voos' já contém dados.")
# Salva as alterações e fecha a conexão
conn.commit()
conn.close()
print("\nConfiguração do banco de dados concluída com sucesso!")
2. app.py
(A Aplicação Web Principal)
Este é o arquivo mais importante. Ele contém toda a lógica da sua aplicação.
# app.py
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from werkzeug.security import generate_password_hash, check_password_hash
import sqlite3
import pyotp # Para o Google Authenticator (2FA)
import qrcode
from io import BytesIO
import base64
from datetime import datetime
import uuid # Para gerar protocolos de ticket únicos
# --- Configuração da Aplicação Flask ---
app = Flask(__name__)
app.config['SECRET_KEY'] = 'uma-chave-secreta-muito-dificil-de-adivinhar'
# --- Configuração do Flask-Login ---
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login' # Redireciona para a página de login se não estiver logado
# --- Classe de Usuário para o Flask-Login ---
class User(UserMixin):
def __init__(self, id, usuario):
self.id = id
self.usuario = usuario
@login_manager.user_loader
def load_user(user_id):
conn = get_db_connection()
user_data = conn.execute('SELECT * FROM usuarios WHERE id = ?', (user_id,)).fetchone()
conn.close()
if user_data:
return User(id=user_data['id'], usuario=user_data['usuario'])
return None
# --- Conexão com o Banco de Dados ---
def get_db_connection():
conn = sqlite3.connect('voos_db.sqlite')
conn.row_factory = sqlite3.Row # Permite acessar colunas por nome
return conn
# --- ROTAS DA APLICAÇÃO ---
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
usuario = request.form['usuario']
senha = request.form['senha']
token_2fa = request.form['token_2fa']
conn = get_db_connection()
user_data = conn.execute('SELECT * FROM usuarios WHERE usuario = ?', (usuario,)).fetchone()
if not user_data or not check_password_hash(user_data['senha_hash'], senha):
flash('Usuário ou senha inválida.', 'danger')
conn.close()
return redirect(url_for('login'))
# Verifica o 2FA
if user_data['otp_secret']:
totp = pyotp.TOTP(user_data['otp_secret'])
if not totp.verify(token_2fa):
flash('Token 2FA inválido!', 'danger')
conn.close()
return redirect(url_for('login'))
else:
flash('Por favor, configure o 2FA para sua segurança.', 'warning')
conn.close()
user_obj = User(id=user_data['id'], usuario=user_data['usuario'])
login_user(user_obj)
return redirect(url_for('index'))
return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
usuario = request.form['usuario']
senha = request.form['senha']
conn = get_db_connection()
# Verifica se usuário já existe
if conn.execute('SELECT id FROM usuarios WHERE usuario = ?', (usuario,)).fetchone():
flash('Este nome de usuário já existe.', 'danger')
conn.close()
return redirect(url_for('register'))
senha_hash = generate_password_hash(senha)
conn.execute('INSERT INTO usuarios (usuario, senha_hash) VALUES (?, ?)', (usuario, senha_hash))
conn.commit()
conn.close()
flash('Usuário registrado com sucesso! Faça o login.', 'success')
return redirect(url_for('login'))
return render_template('register.html')
@app.route('/setup_2fa')
@login_required
def setup_2fa():
conn = get_db_connection()
secret = conn.execute('SELECT otp_secret FROM usuarios WHERE id = ?', (current_user.id,)).fetchone()[0]
# Gera um novo segredo se o usuário ainda não tiver um
if secret is None:
secret = pyotp.random_base32()
conn.execute('UPDATE usuarios SET otp_secret = ? WHERE id = ?', (secret, current_user.id))
conn.commit()
conn.close()
# Gera o QR Code
uri = pyotp.totp.TOTP(secret).provisioning_uri(name=current_user.usuario, issuer_name='App Vôos Ticket')
img = qrcode.make(uri)
buffered = BytesIO()
img.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode()
return render_template('setup_2fa.html', secret=secret, qr_code=img_str)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
@app.route('/')
@login_required
def index():
conn = get_db_connection()
# Lógica de filtro pelo calendário
data_filtro = request.args.get('data') # Pega a data da URL (?data=YYYY-MM-DD)
query = 'SELECT * FROM voos'
params = []
if data_filtro:
query += ' WHERE date(partida) = ?'
params.append(data_filtro)
query += ' ORDER BY partida ASC'
voos = conn.execute(query, params).fetchall()
conn.close()
return render_template('index.html', voos=voos, data_filtro=data_filtro)
@app.route('/criar_ticket/<int:voo_id>', methods=['POST'])
@login_required
def criar_ticket(voo_id):
nota = request.form['nota']
if len(nota) > 10000:
flash('O campo de nota não pode exceder 10.000 caracteres.', 'danger')
return redirect(url_for('index'))
conn = get_db_connection()
# Gera um protocolo único para o ticket
protocolo = f"TICKET-{uuid.uuid4().hex[:8].upper()}"
conn.execute(
'INSERT INTO tickets (protocolo, id_usuario, id_voo, nota, data_criacao) VALUES (?, ?, ?, ?, ?)',
(protocolo, current_user.id, voo_id, nota, datetime.now())
)
conn.commit()
conn.close()
flash(f'Ticket com protocolo {protocolo} criado com sucesso!', 'success')
return redirect(url_for('ver_tickets'))
@app.route('/meus_tickets')
@login_required
def ver_tickets():
conn = get_db_connection()
meus_tickets = conn.execute('''
SELECT t.protocolo, t.nota, t.data_criacao, v.numero_voo, v.origem, v.destino, v.partida
FROM tickets t
JOIN voos v ON t.id_voo = v.id
WHERE t.id_usuario = ?
ORDER BY t.data_criacao DESC
''', (current_user.id,)).fetchall()
conn.close()
return render_template('view_tickets.html', tickets=meus_tickets)
# --- Gerenciamento de Usuário (exemplo simples) ---
@app.route('/delete_user/<int:user_id>', methods=['POST'])
@login_required
def delete_user(user_id):
# Em um app real, aqui teria uma lógica para verificar se o usuário é admin
if current_user.id == user_id:
flash("Você não pode deletar a si mesmo.", "danger")
return redirect(url_for('index'))
conn = get_db_connection()
conn.execute('DELETE FROM tickets WHERE id_usuario = ?', (user_id,))
conn.execute('DELETE FROM usuarios WHERE id = ?', (user_id,))
conn.commit()
conn.close()
flash("Usuário deletado com sucesso.", "success")
return redirect(url_for('index')) # Idealmente, redirecionar para uma página de admin
if __name__ == '__main__':
# Roda a aplicação
# host='0.0.0.0' torna a aplicação acessível na sua rede local
print("Aplicação iniciada. Acesse no seu navegador.")
print(f" - Na sua máquina: http://127.0.0.1:8080")
print(f" - Em outros dispositivos na mesma rede: http://192.168.0.X:8080 (substitua pelo IP da sua máquina)")
app.run(host='0.0.0.0', port=8080, debug=True)
3. Arquivos HTML (Dentro da pasta /templates
)
Crie os arquivos HTML a seguir. Eles usam o framework Bootstrap para um visual limpo e moderno.
templates/base.html
<!doctype html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Sistema de Voos{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; }
.navbar { margin-bottom: 20px; }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('index') }}">Ticket System</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
{% if current_user.is_authenticated %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('index') }}">Voos</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('ver_tickets') }}">Meus Tickets</a></li>
{% endif %}
</ul>
<ul class="navbar-nav">
{% if current_user.is_authenticated %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('setup_2fa') }}">Configurar 2FA</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('logout') }}">Logout ({{ current_user.usuario }})</a></li>
{% else %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('login') }}">Login</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('register') }}">Registrar</a></li>
{% endif %}
</ul>
</div>
</div>
</nav>
<main class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
templates/login.html
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
<div class="mb-3">
<label for="usuario" class="form-label">Usuário</label>
<input type="text" class="form-control" id="usuario" name="usuario" required>
</div>
<div class="mb-3">
<label for="senha" class="form-label">Senha</label>
<input type="password" class="form-control" id="senha" name="senha" required>
</div>
<div class="mb-3">
<label for="token_2fa" class="form-label">Token 2FA (Google Authenticator)</label>
<input type="text" class="form-control" id="token_2fa" name="token_2fa" placeholder="Deixe em branco se não configurado" autocomplete="off">
</div>
<button type="submit" class="btn btn-primary">Entrar</button>
</form>
<p class="mt-3">Não tem uma conta? <a href="{{ url_for('register') }}">Registre-se aqui</a>.</p>
{% endblock %}
templates/register.html
{% extends "base.html" %}
{% block title %}Registrar{% endblock %}
{% block content %}
<h2>Registrar Novo Usuário</h2>
<form method="post">
<div class="mb-3">
<label for="usuario" class="form-label">Usuário</label>
<input type="text" class="form-control" id="usuario" name="usuario" required>
</div>
<div class="mb-3">
<label for="senha" class="form-label">Senha</label>
<input type="password" class="form-control" id="senha" name="senha" required>
</div>
<button type="submit" class="btn btn-success">Registrar</button>
</form>
{% endblock %}
templates/setup_2fa.html
{% extends "base.html" %}
{% block title %}Configurar 2FA{% endblock %}
{% block content %}
<h2>Configurar Autenticação de Dois Fatores (2FA)</h2>
<p>Escaneie o QR Code abaixo com o seu aplicativo Google Authenticator (ou similar).</p>
<div class="text-center">
<img src="data:image/png;base64,{{ qr_code }}" alt="QR Code 2FA">
</div>
<p class="mt-3">Se não puder escanear, insira manualmente a chave secreta:</p>
<p><code>{{ secret }}</code></p>
<hr>
<p>Após configurar, você precisará fornecer o código gerado pelo app sempre que fizer login.</p>
<a href="{{ url_for('index') }}" class="btn btn-primary">Voltar para a Página Principal</a>
{% endblock %}
templates/index.html
{% extends "base.html" %}
{% block title %}Voos Disponíveis{% endblock %}
{% block content %}
<h2>Painel de Voos</h2>
<form method="get" class="row g-3 align-items-center mb-4">
<div class="col-auto">
<label for="data" class="form-label">Filtrar por data:</label>
</div>
<div class="col-auto">
<input type="date" id="data" name="data" class="form-control"
value="{{ data_filtro if data_filtro else '' }}"
min="1970-01-01" max="2400-12-31">
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary">Filtrar</button>
</div>
</form>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Voo</th>
<th>Companhia</th>
<th>Origem</th>
<th>Destino</th>
<th>Partida</th>
<th>Chegada</th>
<th>Status</th>
<th>Ação</th>
</tr>
</thead>
<tbody>
{% for voo in voos %}
<tr>
<td>{{ voo['numero_voo'] }}</td>
<td>{{ voo['companhia_aerea'] }}</td>
<td>{{ voo['origem'] }}</td>
<td>{{ voo['destino'] }}</td>
<td>{{ voo['partida'] }}</td>
<td>{{ voo['chegada'] }}</td>
<td>{{ voo['status'] }}</td>
<td>
<form method="post" action="{{ url_for('criar_ticket', voo_id=voo['id']) }}">
<div class="input-group">
<textarea name="nota" class="form-control" placeholder="Adicionar nota (até 10000 caracteres)" rows="2" maxlength="10000"></textarea>
<button class="btn btn-success btn-sm" type="submit">Criar Ticket</button>
</div>
</form>
</td>
</tr>
{% else %}
<tr>
<td colspan="8" class="text-center">Nenhum voo encontrado para a data selecionada.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
templates/view_tickets.html
{% extends "base.html" %}
{% block title %}Meus Tickets{% endblock %}
{% block content %}
<h2>Meus Tickets Criados</h2>
{% if tickets %}
<div class="list-group">
{% for ticket in tickets %}
<div class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Protocolo: {{ ticket['protocolo'] }}</h5>
<small>Criado em: {{ ticket['data_criacao'] }}</small>
</div>
<p class="mb-1"><strong>Voo:</strong> {{ ticket['numero_voo'] }} ({{ ticket['origem'] }} -> {{ ticket['destino'] }}) | <strong>Partida:</strong> {{ ticket['partida'] }}</p>
<hr>
<p class="mb-1"><strong>Sua Nota:</strong></p>
<p class="mb-1" style="white-space: pre-wrap;">{{ ticket['nota'] }}</p>
</div>
{% endfor %}
</div>
{% else %}
<p>Você ainda não criou nenhum ticket.</p>
{% endif %}
{% endblock %}
Passo 4: Como Rodar a Aplicação
Prepare o Banco de Dados: Abra o terminal na pasta do projeto e rode o script de setup uma única vez:
Bashpython database_setup.py
Isso vai criar o arquivo
voos_db.sqlite
com todas as tabelas e dados.Inicie a Aplicação Web: Agora, rode o arquivo principal:
Bashpython app.py
Acesse no Navegador:
No seu computador: Abra o navegador e acesse
http://127.0.0.1:8080
ouhttp://localhost:8080
.Em outro dispositivo (celular, tablet) na mesma rede Wi-Fi: Você precisa descobrir o IP local do seu computador (ex:
192.168.0.15
). No terminal do seu computador, você pode usaripconfig
(Windows) ouifconfig
(Mac/Linux) para achar. Depois, acesse no navegador do outro dispositivo:http://SEU_IP_LOCAL:8080
(ex:http://192.168.0.15:8080
).
Sobre o Acesso Externo (Internet)
Para que alguém fora da sua rede acesse usando seu IP público (201.81.52.233
), você precisaria configurar o "Port Forwarding" (Redirecionamento de Portas) no seu roteador. Isso é uma configuração avançada e de segurança que diz ao seu roteador para enviar todo o tráfego que chega na porta 8080
para o seu computador. Por segurança, o ideal para acesso externo é usar servidores web mais robustos (como Gunicorn ou Nginx) e configurar HTTPS.
Este projeto que criamos é o alicerce completo para tudo que você pediu. Ele é seguro para uso local e demonstra todas as funcionalidades solicitadas.
Olá! Com certeza. "Veen" é como muitas pessoas pronunciam venv
, que é a ferramenta padrão do Python para criar ambientes virtuais. Usar um venv
é uma das melhores práticas na programação Python, e no Linux Mint é bem simples de fazer.
Vou te guiar passo a passo.
O que é um venv
e por que usar?
Imagine que cada projeto que você cria é uma casa. Cada casa precisa de suas próprias ferramentas (bibliotecas).
Projeto A (uma aplicação web) precisa da ferramenta
Flask
na versão2.0
.Projeto B (um script de análise de dados) precisa da ferramenta
Pandas
e doFlask
na versão3.0
.
Se você instalar todas as ferramentas "soltas" no seu sistema operacional, logo terá um conflito: qual versão do Flask
usar? A 2.0
ou a 3.0
?
O venv
resolve isso criando uma "bolha" ou uma "caixa de ferramentas" isolada para cada projeto. Assim, as ferramentas do Projeto A não interferem nas do Projeto B.
Vantagens:
Organização: Cada projeto tem suas próprias dependências.
Evitar Conflitos: Versões diferentes de uma mesma biblioteca podem coexistir em projetos diferentes.
Reprodutibilidade: Você pode facilmente gerar uma lista de todas as ferramentas usadas (
requirements.txt
) e recriar o ambiente em outro computador.Não "sujar" o sistema: Você mantém a instalação principal do Python do seu Linux Mint limpa.
Passo a Passo para Criar e Usar um venv
no Linux Mint
Passo 1: Abra o Terminal
A forma mais fácil é usar o atalho: Ctrl + Alt + T
.
Passo 2: Garanta que o venv
está instalado
O Python 3 já vem com o Linux Mint, mas o módulo específico do venv
às vezes precisa ser instalado separadamente. É um pacote chamado python3-venv
.
Rode o comando abaixo para atualizar a lista de pacotes e instalar o venv
:
sudo apt update && sudo apt install python3-venv -y
sudo
: Executa o comando como superusuário (administrador).apt update
: Atualiza a lista de pacotes disponíveis.apt install python3-venv
: Instala o pacote dovenv
.-y
: Responde "sim" automaticamente para a instalação.
Passo 3: Crie a Pasta do seu Projeto
É uma boa prática criar o ambiente virtual dentro da pasta do projeto ao qual ele pertence.
# Cria uma nova pasta chamada 'meu_projeto_python'
mkdir meu_projeto_python
# Entra na pasta recém-criada
cd meu_projeto_python
Passo 4: Crie o Ambiente Virtual
Agora, dentro da pasta do seu projeto, use o seguinte comando para criar o ambiente:
python3 -m venv venv
Vamos entender o comando:
python3
: Chama o interpretador Python 3.-m venv
: Diz ao Python para executar o módulovenv
.venv
(o último): É o nome da pasta que será criada para guardar seu ambiente virtual. Usarvenv
como nome é uma convenção muito comum e recomendada.
Após rodar o comando, se você listar os arquivos (ls
), verá uma nova pasta chamada venv
.
usuario@mint:~/meu_projeto_python$ ls
venv
Passo 5: Ative o Ambiente Virtual
Criar o ambiente não o ativa. Para "entrar na bolha", você precisa ativá-lo com o seguinte comando:
source venv/bin/activate
Você saberá que funcionou porque o seu prompt do terminal mudará, mostrando o nome do ambiente entre parênteses.
Antes:
usuario@mint:~/meu_projeto_python$
Depois:
(venv) usuario@mint:~/meu_projeto_python$
Esse (venv)
indica que seu ambiente virtual está ativo.
Passo 6: Use o Ambiente
Com o ambiente ativo, você pode instalar bibliotecas usando pip
. Elas serão instaladas apenas dentro desta "bolha".
Por exemplo, para instalar a biblioteca requests
:
(venv) usuario@mint:~/meu_projeto_python$ pip install requests
Para ver o que está instalado apenas neste ambiente:
(venv) usuario@mint:~/meu_projeto_python$ pip list
Passo 7: Desative o Ambiente
Quando terminar de trabalhar no seu projeto, você pode "sair da bolha" digitando simplesmente:
(venv) usuario@mint:~/meu_projeto_python$ deactivate
O prompt do terminal voltará ao normal, sem o (venv)
.
Resumo Rápido (Comandos Essenciais)
# 1. Instalar o pacote (só na primeira vez)
sudo apt update && sudo apt install python3-venv -y
# 2. Criar pasta do projeto e entrar nela
mkdir meu_projeto
cd meu_projeto
# 3. Criar o ambiente virtual
python3 -m venv venv
# 4. Ativar o ambiente
source venv/bin/activate
# 5. Trabalhar e instalar pacotes (exemplo)
pip install flask
# ... seu código aqui ...
# 6. Desativar quando terminar
deactivate
Dica Extra: Gerenciando Dependências com requirements.txt
Depois de instalar todas as bibliotecas que seu projeto precisa, você pode criar um "arquivo de receita" para que outras pessoas (ou você mesmo no futuro) possam recriar o ambiente facilmente.
Com o ambiente ativo, gere o arquivo:
Bashpip freeze > requirements.txt
Isso cria um arquivo
requirements.txt
com a lista de pacotes e suas versões exatas.Para instalar tudo a partir desse arquivo em um novo ambiente, o comando é:
Bashpip install -r requirements.txt
Pronto! Agora você sabe como gerenciar seus projetos Python de forma profissional no Linux Mint.
Comentários
Postar um comentário
Obrigado, por responder. Até mais.