Cambio de rutas: ahora portada muestra noticias y gestión de feeds pasa a /feeds. Mejoras en navegación y backup.

This commit is contained in:
jlimolina 2025-05-26 17:50:55 +02:00
parent b3dc6a4ac2
commit d7cabbb2c6
5 changed files with 222 additions and 61 deletions

206
app.py
View file

@ -1,10 +1,12 @@
from flask import Flask, render_template, request, redirect
from flask import Flask, render_template, request, redirect, url_for, Response
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime
import feedparser
import hashlib
import re
import mysql.connector
import csv
from io import StringIO
app = Flask(__name__)
@ -15,61 +17,11 @@ DB_CONFIG = {
'database': 'noticiasrss'
}
# Página principal: muestra los feeds y el formulario con selects de categoría, continente y país
# ======================================
# Página principal: últimas noticias
# ======================================
@app.route('/')
def index():
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
# Feeds con país/categoría (incluye nombres)
cursor.execute("""
SELECT f.id, f.nombre, f.url, f.categoria_id, f.pais_id, f.activo, c.nombre, p.nombre
FROM feeds f
LEFT JOIN categorias_estandar c ON f.categoria_id = c.id
LEFT JOIN paises p ON f.pais_id = p.id
""")
feeds = cursor.fetchall()
# Categorías, continentes y países para los selects
cursor.execute("SELECT id, nombre FROM categorias_estandar ORDER BY nombre")
categorias = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM continentes ORDER BY nombre")
continentes = cursor.fetchall()
cursor.execute("SELECT id, nombre, continente_id FROM paises ORDER BY nombre")
paises = cursor.fetchall()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al leer feeds/categorías/países: {db_err}", exc_info=True)
feeds, categorias, continentes, paises = [], [], [], []
finally:
if conn:
conn.close()
return render_template("index.html", feeds=feeds, categorias=categorias, continentes=continentes, paises=paises)
# Añadir feed: ahora requiere país y categoría
@app.route('/add', methods=['POST'])
def add_feed():
nombre = request.form.get('nombre')
url = request.form.get('url')
categoria_id = request.form.get('categoria_id')
pais_id = request.form.get('pais_id')
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute(
"INSERT INTO feeds (nombre, url, categoria_id, pais_id) VALUES (%s, %s, %s, %s)",
(nombre, url, categoria_id, pais_id)
)
conn.commit()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al agregar feed: {db_err}", exc_info=True)
finally:
if conn:
conn.close()
return redirect('/')
# Mostrar noticias, con filtros por categoría, continente y país
@app.route('/noticias')
def show_noticias():
def home():
conn = None
noticias = []
categorias = []
@ -131,6 +83,150 @@ def show_noticias():
pais_id=int(pais_id) if pais_id else None
)
# ======================================
# Gestión de feeds en /feeds
# ======================================
@app.route('/feeds')
def feeds():
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
# Feeds con país/categoría (incluye nombres)
cursor.execute("""
SELECT f.id, f.nombre, f.url, f.categoria_id, f.pais_id, f.activo, c.nombre, p.nombre
FROM feeds f
LEFT JOIN categorias_estandar c ON f.categoria_id = c.id
LEFT JOIN paises p ON f.pais_id = p.id
""")
feeds = cursor.fetchall()
# Categorías, continentes y países para los selects
cursor.execute("SELECT id, nombre FROM categorias_estandar ORDER BY nombre")
categorias = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM continentes ORDER BY nombre")
continentes = cursor.fetchall()
cursor.execute("SELECT id, nombre, continente_id FROM paises ORDER BY nombre")
paises = cursor.fetchall()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al leer feeds/categorías/países: {db_err}", exc_info=True)
feeds, categorias, continentes, paises = [], [], [], []
finally:
if conn:
conn.close()
return render_template("index.html", feeds=feeds, categorias=categorias, continentes=continentes, paises=paises)
# Añadir feed
@app.route('/add', methods=['POST'])
def add_feed():
nombre = request.form.get('nombre')
url = request.form.get('url')
categoria_id = request.form.get('categoria_id')
pais_id = request.form.get('pais_id')
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute(
"INSERT INTO feeds (nombre, url, categoria_id, pais_id) VALUES (%s, %s, %s, %s)",
(nombre, url, categoria_id, pais_id)
)
conn.commit()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al agregar feed: {db_err}", exc_info=True)
finally:
if conn:
conn.close()
return redirect(url_for('feeds'))
# Editar feed
@app.route('/edit/<int:feed_id>', methods=['GET', 'POST'])
def edit_feed(feed_id):
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor(dictionary=True)
if request.method == 'POST':
nombre = request.form.get('nombre')
url_feed = request.form.get('url')
categoria_id = request.form.get('categoria_id')
pais_id = request.form.get('pais_id')
activo = 1 if request.form.get('activo') == 'on' else 0
cursor.execute(
"UPDATE feeds SET nombre=%s, url=%s, categoria_id=%s, pais_id=%s, activo=%s WHERE id=%s",
(nombre, url_feed, categoria_id, pais_id, activo, feed_id)
)
conn.commit()
return redirect(url_for('feeds'))
# GET: Obtener datos actuales del feed
cursor.execute("SELECT * FROM feeds WHERE id = %s", (feed_id,))
feed = cursor.fetchone()
cursor.execute("SELECT id, nombre FROM categorias_estandar ORDER BY nombre")
categorias = cursor.fetchall()
cursor.execute("SELECT id, nombre FROM paises ORDER BY nombre")
paises = cursor.fetchall()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al editar feed: {db_err}", exc_info=True)
feed, categorias, paises = {}, [], []
finally:
if conn:
conn.close()
return render_template('edit_feed.html', feed=feed, categorias=categorias, paises=paises)
# Eliminar feed
@app.route('/delete/<int:feed_id>')
def delete_feed(feed_id):
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute("DELETE FROM feeds WHERE id=%s", (feed_id,))
conn.commit()
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al eliminar feed: {db_err}", exc_info=True)
finally:
if conn:
conn.close()
return redirect(url_for('feeds'))
# Backup de feeds a CSV
@app.route('/backup_feeds')
def backup_feeds():
conn = None
try:
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
cursor.execute("""
SELECT f.id, f.nombre, f.url, f.categoria_id, c.nombre AS categoria, f.pais_id, p.nombre AS pais, f.activo
FROM feeds f
LEFT JOIN categorias_estandar c ON f.categoria_id = c.id
LEFT JOIN paises p ON f.pais_id = p.id
""")
feeds = cursor.fetchall()
header = [desc[0] for desc in cursor.description]
except mysql.connector.Error as db_err:
app.logger.error(f"[DB ERROR] Al hacer backup de feeds: {db_err}", exc_info=True)
return "Error generando backup.", 500
finally:
if conn:
conn.close()
# CSV en memoria
si = StringIO()
cw = csv.writer(si)
cw.writerow(header)
cw.writerows(feeds)
output = si.getvalue()
si.close()
return Response(
output,
mimetype="text/csv",
headers={"Content-Disposition": "attachment;filename=feeds_backup.csv"}
)
# (Antiguo /noticias, por compatibilidad)
@app.route('/noticias')
def show_noticias():
return home()
def fetch_and_store():
conn = None
try: