${noticia.titulo}
+${noticia.cuerpo}
+diff --git a/conexionbd.py b/conexionbd.py new file mode 100644 index 0000000..c28041e --- /dev/null +++ b/conexionbd.py @@ -0,0 +1,10 @@ +from sqlalchemy import create_engine +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, declarative_base + +SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db" + +engine = create_engine(SQLALCHEMY_DATABASE_URL) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() diff --git a/main.py b/main.py new file mode 100644 index 0000000..57ee586 --- /dev/null +++ b/main.py @@ -0,0 +1,40 @@ +from fastapi import FastAPI, File, UploadFile +from fastapi.staticfiles import StaticFiles +from starlette.responses import FileResponse +from src.routers.noticiarouters import router as noticia_router +from conexionbd import Base, engine +import os + +# Crear todas las tablas en la base de datos +Base.metadata.create_all(bind=engine) + +# Crear la instancia de la aplicación FastAPI +app = FastAPI() + +# Montar directorio estático +app.mount("/static", StaticFiles(directory="static"), name="static") + +# Incluir el router de noticias +app.include_router(noticia_router, prefix="/api/v1") + +# Endpoint para servir el archivo noticiaver.html +@app.get("/") +async def get_index(): + return FileResponse("src/views/noticiaver.html") + +# Endpoint para servir el archivo crearnoticia.html +@app.get("/crearnoticia.html") +async def get_create_news(): + return FileResponse("src/views/crearnoticia.html") + +# Endpoint para manejar la subida de archivos +@app.post("/api/v1/noticias/") +async def create_noticia(titulo: str, cuerpo: str, archivo: UploadFile = File(...)): + # Guarda el archivo + upload_folder = "/static/images" + os.makedirs(upload_folder, exist_ok=True) + file_location = f"{upload_folder}/{archivo.filename}" + with open(file_location, "wb") as file: + file.write(archivo.file.read()) + + return {"titulo": titulo, "cuerpo": cuerpo, "archivo": f"/static/images/{archivo.filename}"} diff --git a/src/controllers/noticiacontroller.py b/src/controllers/noticiacontroller.py new file mode 100644 index 0000000..98f42c9 --- /dev/null +++ b/src/controllers/noticiacontroller.py @@ -0,0 +1,14 @@ +import sys +import os + +# Agregar la ruta del directorio raíz de tu proyecto al sys.path +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +from fastapi import APIRouter +from src.models.noticiamodel import get_crearnoticia + +router = APIRouter() + +@router.get("/") +async def get_index(): + return get_crearnoticia() diff --git a/src/models/noticia.py b/src/models/noticia.py new file mode 100644 index 0000000..5f84133 --- /dev/null +++ b/src/models/noticia.py @@ -0,0 +1,17 @@ +import sys +import os + +# Agregar la ruta del directorio raíz de tu proyecto al sys.path +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +from sqlalchemy import Column, Integer, String, Date +from conexionbd import Base + +class Noticia(Base): + __tablename__ = 'noticias' + + id_noticia = Column(Integer, primary_key=True, index=True) + titulo = Column(String, index=True) + cuerpo = Column(String) + archivo = Column(String) # Ruta del archivo + fecha = Column(Date) diff --git a/src/models/noticiamodel.py b/src/models/noticiamodel.py new file mode 100644 index 0000000..3adc0b1 --- /dev/null +++ b/src/models/noticiamodel.py @@ -0,0 +1,40 @@ +import sys +import os + +# Agregar la ruta del directorio raíz de tu proyecto al sys.path +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +from sqlalchemy.orm import Session +from fastapi import UploadFile +from src.models.noticia import Noticia +from src.models.schemas import NoticiaCreate +from fastapi.responses import FileResponse +import shutil + +def save_file(file: UploadFile, destination: str): + with open(destination, "wb") as buffer: + shutil.copyfileobj(file.file, buffer) + return destination + +def get_crearnoticia(): + return FileResponse("src/views/crearnoticia.html") + +def create_noticia(db: Session, noticia: NoticiaCreate, file: UploadFile): + file_path = save_file(file, f"static/images/{file.filename}") + db_noticia = Noticia(id_noticia=noticia.id_noticia, titulo=noticia.titulo, cuerpo=noticia.cuerpo, + archivo=file_path, fecha=noticia.fecha) + db.add(db_noticia) + db.commit() + db.refresh(db_noticia) + return db_noticia + +def get_noticias(db: Session): + return db.query(Noticia).all() + +def get_noticia(db: Session, noticia_id: int): + return db.query(Noticia).filter(Noticia.id_noticia == noticia_id).first() + +def delete_noticia(db: Session, noticia_id: int): + db.query(Noticia).filter(Noticia.id_noticia == noticia_id).delete() + db.commit() + diff --git a/src/models/schemas.py b/src/models/schemas.py new file mode 100644 index 0000000..0d5c23a --- /dev/null +++ b/src/models/schemas.py @@ -0,0 +1,21 @@ +from pydantic import BaseModel +from datetime import date + +# Actúa como una clase base, reduciendo la duplicación de código y asegurando que los campos comunes estén centralizados. +class NoticiaBase(BaseModel): + titulo: str + cuerpo: str + archivo: str + fecha: date + +# Extiende NoticiaBase y añade campos específicos necesarios solo para la creación. +class NoticiaCreate(NoticiaBase): + id_noticia: int + +# Extiende NoticiaBase y añade campos necesarios para la respuesta de la API, +# junto con configuraciones específicas para la interoperabilidad con SQLAlchemy. +class NoticiaSchema(NoticiaBase): + id_noticia: int + + class Config: + from_attributes = True diff --git a/src/routers/noticiarouters.py b/src/routers/noticiarouters.py new file mode 100644 index 0000000..3c6dd4e --- /dev/null +++ b/src/routers/noticiarouters.py @@ -0,0 +1,81 @@ +import sys +import os +import shutil +from fastapi import HTTPException, Depends, APIRouter, UploadFile, Form +from sqlalchemy.orm import Session +from fastapi.responses import JSONResponse +from fastapi import File + +# Agregar la ruta del directorio raíz de tu proyecto al sys.path +sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) + +from conexionbd import SessionLocal +from src.models.noticiamodel import create_noticia as create_noticia_db, get_noticias as get_noticias_db, get_noticia as get_noticia_db, delete_noticia as delete_noticia_db +from src.models.schemas import NoticiaCreate, NoticiaSchema +from src.models.noticia import Noticia + +router = APIRouter() + +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + +def get_next_noticia_id(db: Session) -> int: + """Obtiene el próximo ID disponible para una nueva noticia.""" + last_noticia = db.query(Noticia).order_by(Noticia.id_noticia.desc()).first() + if last_noticia: + return last_noticia.id_noticia + 1 + else: + return 1 + +@router.post("/noticias/", response_model=NoticiaSchema) +def create_noticia( + titulo: str = Form(...), + cuerpo: str = Form(...), + fecha: str = Form(...), + archivo: UploadFile = File(...), + db: Session = Depends(get_db) +): + # Obtener el próximo ID disponible + id_noticia = get_next_noticia_id(db) + + # Crear el directorio de imágenes si no existe + upload_folder = "static/images" + os.makedirs(upload_folder, exist_ok=True) + + # Guardar el archivo en el directorio y obtener su ruta + file_path = os.path.join(upload_folder, archivo.filename) + with open(file_path, "wb") as file_object: + shutil.copyfileobj(archivo.file, file_object) + + # Crear el objeto NoticiaCreate + noticia_data = NoticiaCreate(id_noticia=id_noticia, titulo=titulo, cuerpo=cuerpo, archivo=file_path, fecha=fecha) + return create_noticia_db(db, noticia_data, archivo) + +@router.get("/noticias/", response_model=list[NoticiaSchema]) +def read_noticias(db: Session = Depends(get_db)): + return get_noticias_db(db) + +@router.get("/noticias/{noticia_id}", response_model=NoticiaSchema) +def read_publicacion(noticia_id: int, db: Session = Depends(get_db)): + db_noticia = get_noticia_db(db, noticia_id) + if db_noticia is None: + raise HTTPException(status_code=404, detail="Publicación no encontrada") + return db_noticia + +@router.delete("/noticias/{noticia_id}", response_model=dict) +def delete_noticia(noticia_id: int, db: Session = Depends(get_db)): + db_noticia = get_noticia_db(db, noticia_id) + if db_noticia is None: + raise HTTPException(status_code=404, detail="Publicación no encontrada") + delete_noticia_db(db, noticia_id) + return {"detail": "Noticia eliminada"} + +@router.get("/noticias/buscar/", response_model=list[NoticiaSchema]) +def search_noticias(query: str, db: Session = Depends(get_db)): + noticias = db.query(Noticia).filter(Noticia.titulo.ilike(f"%{query}%")).all() + return noticias + diff --git a/src/views/crearnoticia.html b/src/views/crearnoticia.html new file mode 100644 index 0000000..f3d0d06 --- /dev/null +++ b/src/views/crearnoticia.html @@ -0,0 +1,65 @@ + + +
+ + +${noticia.cuerpo}
+