{{ noticia.titulo }}
+ +{{ noticia.resumen | striptags | safe_html | truncate(280) }}
+diff --git a/app.py b/app.py index dc42757..9c521c7 100644 --- a/app.py +++ b/app.py @@ -43,30 +43,46 @@ def safe_html(text): allowed_attrs = {'a': ['href', 'title'], 'img': ['src', 'alt']} return bleach.clean(text, tags=allowed_tags, attributes=allowed_attrs, strip=True) +# En app.py, reemplaza tu función home() con esta: + +# En app.py + @app.route("/") def home(): - noticias, categorias, continentes, paises = [], [], [], [] + # ... (el código inicial para obtener los parámetros no cambia) ... cat_id = request.args.get("categoria_id") cont_id = request.args.get("continente_id") pais_id = request.args.get("pais_id") fecha_filtro = request.args.get("fecha") + q = request.args.get("q", "").strip() # <--- NUEVO: Obtenemos el término de búsqueda + + # ... (el resto del código hasta la construcción de la consulta) ... + # (se omite por brevedad, es idéntico) try: with get_conn() as conn: with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cursor: + # ... (las consultas para obtener categorías, continentes y países no cambian) ... cursor.execute("SELECT id, nombre FROM categorias ORDER BY nombre") categorias = cursor.fetchall() cursor.execute("SELECT id, nombre FROM continentes ORDER BY nombre") continentes = cursor.fetchall() - if cont_id: - cursor.execute("SELECT id, nombre, continente_id FROM paises WHERE continente_id = %s ORDER BY nombre", (cont_id,)) - else: - cursor.execute("SELECT id, nombre, continente_id FROM paises ORDER BY nombre") + cursor.execute("SELECT id, nombre, continente_id FROM paises ORDER BY nombre") paises = cursor.fetchall() + sql_params, conditions = [], [] + # El SELECT ahora puede incluir el ranking de la búsqueda sql_base = "SELECT n.fecha, n.titulo, n.resumen, n.url, n.imagen_url, c.nombre AS categoria, p.nombre AS pais, co.nombre AS continente FROM noticias n LEFT JOIN categorias c ON n.categoria_id = c.id LEFT JOIN paises p ON n.pais_id = p.id LEFT JOIN continentes co ON p.continente_id = co.id" + # === INICIO DE LA MODIFICACIÓN DE LA CONSULTA === + if q: + # Convierte el término de búsqueda para que busque palabras completas + # Ejemplo: "guerra ucrania" -> "guerra & ucrania" + search_query = " & ".join(q.split()) + conditions.append("n.tsv @@ to_tsquery('spanish', %s)") + sql_params.append(search_query) + if cat_id: conditions.append("n.categoria_id = %s"); sql_params.append(cat_id) if pais_id: conditions.append("n.pais_id = %s"); sql_params.append(pais_id) elif cont_id: conditions.append("p.continente_id = %s"); sql_params.append(cont_id) @@ -74,25 +90,46 @@ def home(): if fecha_filtro: try: fecha_obj = datetime.strptime(fecha_filtro, '%Y-%m-%d') - fecha_inicio = fecha_obj - fecha_fin = fecha_obj + timedelta(days=1) - conditions.append("n.fecha >= %s AND n.fecha < %s") - sql_params.extend([fecha_inicio, fecha_fin]) + conditions.append("n.fecha::date = %s") + sql_params.append(fecha_obj.date()) except ValueError: flash("Formato de fecha no válido. Use AAAA-MM-DD.", "error") fecha_filtro = None - if conditions: sql_base += " WHERE " + " AND ".join(conditions) - sql_final = sql_base + " ORDER BY n.fecha DESC NULLS LAST LIMIT 50" + if conditions: + sql_base += " WHERE " + " AND ".join(conditions) + + # Si hay búsqueda, ordena por relevancia. Si no, por fecha. + if q: + search_query_ts = " & ".join(q.split()) + sql_base += " ORDER BY ts_rank(n.tsv, to_tsquery('spanish', %s)) DESC, n.fecha DESC" + sql_params.append(search_query_ts) + else: + sql_base += " ORDER BY n.fecha DESC NULLS LAST" + + sql_final = sql_base + " LIMIT 50" + # === FIN DE LA MODIFICACIÓN DE LA CONSULTA === + cursor.execute(sql_final, tuple(sql_params)) noticias = cursor.fetchall() except psycopg2.Error as db_err: app.logger.error(f"[DB ERROR] Al leer noticias: {db_err}", exc_info=True) flash("Error de base de datos al cargar las noticias.", "error") + noticias, categorias, continentes, paises = [], [], [], [] # Resetea en caso de error - return render_template("noticias.html", noticias=noticias, categorias=categorias, continentes=continentes, paises=paises, - cat_id=int(cat_id) if cat_id else None, cont_id=int(cont_id) if cont_id else None, - pais_id=int(pais_id) if pais_id else None, fecha_filtro=fecha_filtro) + if request.headers.get('X-Requested-With') == 'XMLHttpRequest': + return render_template('_noticias_list.html', noticias=noticias) + + return render_template("noticias.html", + noticias=noticias, + categorias=categorias, + continentes=continentes, + paises=paises, + cat_id=int(cat_id) if cat_id else None, + cont_id=int(cont_id) if cont_id else None, + pais_id=int(pais_id) if pais_id else None, + fecha_filtro=fecha_filtro, + q=q) # <--- NUEVO: Pasamos el término de búsqueda a la plantilla @app.route("/feeds") def dashboard(): diff --git a/templates/_noticias_list.html b/templates/_noticias_list.html new file mode 100644 index 0000000..bf32c7d --- /dev/null +++ b/templates/_noticias_list.html @@ -0,0 +1,24 @@ +
{{ noticia.resumen | striptags | safe_html | truncate(280) }}
+No hay noticias que mostrar con los filtros seleccionados.
+Tus fuentes de información, en un solo lugar.
- ⚙️ Gestionar Feeds -Tus fuentes de información, en un solo lugar.
+ + Gestionar Feeds + +