#!/usr/bin/env bash
set -e
Crear estructura
mkdir -p .github/workflows app/templates tests
Archivos base
echo "pycache/
*.pyc
.env
test.db
venv/" > .gitignore
echo "DATABASE_URL=sqlite:///./test.db
HOST=0.0.0.0
PORT=8000" > .env
echo "fastapi
uvicorn[standard]
sqlmodel
jinja2
apscheduler
pytest
python-dotenv" > requirements.txt
echo "# Buscador FastAPI
Proyecto de ejemplo con FastAPI, SQLModel, Jinja2 y APScheduler." > README.md
echo "FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]" > Dockerfile
echo "web: uvicorn app.main:app --host 0.0.0.0 --port $PORT" > Procfile
CI
cat > .github/workflows/ci.yml << 'EOF'
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest --maxfail=1 --disable-warnings -q
EOF
Código Python
echo "from fastapi import FastAPI, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from app.database import init_db, get_session
from app import crud, scheduler
app = FastAPI()
templates = Jinja2Templates(directory="app/templates")
@app.on_event("startup")
async def on_startup():
init_db()
scheduler.start_scheduler()
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/search", response_class=HTMLResponse)
async def search(request: Request):
form = await request.form()
query = form.get("query", "")
results = crud.search_books(next(get_session()), query)
return templates.TemplateResponse("results.html", {
"request": request,
"query": query,
"results": results
})" > app/main.py
echo "from sqlmodel import SQLModel, create_engine, Session
import os
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL, echo=True)
def init_db():
from app.models import Book
SQLModel.metadata.create_all(engine)
def get_session():
with Session(engine) as session:
yield session" > app/database.py
echo "from sqlmodel import SQLModel, Field
class Book(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
title: str
author: str
published_year: int" > app/models.py
echo "from sqlmodel import SQLModel
class BookCreate(SQLModel):
title: str
author: str
published_year: int" > app/schemas.py
echo "from sqlmodel import select
from .models import Book
def search_books(session, query: str):
stmt = select(Book).where(Book.title.contains(query))
return session.exec(stmt).all()" > app/crud.py
echo "from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler()
def scheduled_task():
print("Tarea programada ejecutada.")
def start_scheduler():
scheduler.add_job(scheduled_task, "interval", hours=1)
scheduler.start()" > app/scheduler.py
echo "
<title>Buscador FastAPI</title>
Buscador de Libros
Buscar
" > app/templates/index.html
echo "
<title>Resultados</title>
Resultados para '{{ query }}'
{% for book in results %}
- {{ book.title }} - {{ book.author }} ({{ book.published_year }})
{% else %}
- No se encontraron libros.
{% endfor %}
Volver
" > app/templates/results.html
echo "from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
def test_search_no_results():
response = client.post("/search", data={"query": "NoExiste"})
assert response.status_code == 200
assert "No se encontraron libros" in response.text" > tests/test_main.py
echo "Proyecto generado correctamente ✅"
#!/usr/bin/env bash
set -e
Crear estructura
mkdir -p .github/workflows app/templates tests
Archivos base
echo "pycache/
*.pyc
.env
test.db
venv/" > .gitignore
echo "DATABASE_URL=sqlite:///./test.db
HOST=0.0.0.0
PORT=8000" > .env
echo "fastapi
uvicorn[standard]
sqlmodel
jinja2
apscheduler
pytest
python-dotenv" > requirements.txt
echo "# Buscador FastAPI
Proyecto de ejemplo con FastAPI, SQLModel, Jinja2 y APScheduler." > README.md
echo "FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]" > Dockerfile
echo "web: uvicorn app.main:app --host 0.0.0.0 --port $PORT" > Procfile
CI
cat > .github/workflows/ci.yml << 'EOF'
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest --maxfail=1 --disable-warnings -q
EOF
Código Python
echo "from fastapi import FastAPI, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
from app.database import init_db, get_session
from app import crud, scheduler
app = FastAPI()
templates = Jinja2Templates(directory="app/templates")
@app.on_event("startup")
async def on_startup():
init_db()
scheduler.start_scheduler()
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.post("/search", response_class=HTMLResponse)
async def search(request: Request):
form = await request.form()
query = form.get("query", "")
results = crud.search_books(next(get_session()), query)
return templates.TemplateResponse("results.html", {
"request": request,
"query": query,
"results": results
})" > app/main.py
echo "from sqlmodel import SQLModel, create_engine, Session
import os
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL, echo=True)
def init_db():
from app.models import Book
SQLModel.metadata.create_all(engine)
def get_session():
with Session(engine) as session:
yield session" > app/database.py
echo "from sqlmodel import SQLModel, Field
class Book(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
title: str
author: str
published_year: int" > app/models.py
echo "from sqlmodel import SQLModel
class BookCreate(SQLModel):
title: str
author: str
published_year: int" > app/schemas.py
echo "from sqlmodel import select
from .models import Book
def search_books(session, query: str):
stmt = select(Book).where(Book.title.contains(query))
return session.exec(stmt).all()" > app/crud.py
echo "from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler()
def scheduled_task():
print("Tarea programada ejecutada.")
def start_scheduler():
scheduler.add_job(scheduled_task, "interval", hours=1)
scheduler.start()" > app/scheduler.py
echo "
<title>Buscador FastAPI</title>Buscador de Libros
Buscar " > app/templates/index.htmlecho "
<title>Resultados</title>Resultados para '{{ query }}'
{% for book in results %}- {{ book.title }} - {{ book.author }} ({{ book.published_year }})
{% else %}
- No se encontraron libros.
{% endfor %}
Volver " > app/templates/results.htmlecho "from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
def test_search_no_results():
response = client.post("/search", data={"query": "NoExiste"})
assert response.status_code == 200
assert "No se encontraron libros" in response.text" > tests/test_main.py
echo "Proyecto generado correctamente ✅"