Seed all Pokemon species and add admin pagination
- Update fetch_pokeapi.py to import all 1025 Pokemon species instead of only those appearing in encounters - Add paginated response for /pokemon endpoint with total count - Add pagination controls to AdminPokemon page (First/Prev/Next/Last) - Show current page and total count in admin UI - Add bean for Pokemon forms support task - Update UX improvements bean with route grouping polish item Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ from app.schemas.pokemon import (
|
||||
BulkImportItem,
|
||||
BulkImportResult,
|
||||
EvolutionResponse,
|
||||
PaginatedPokemonResponse,
|
||||
PokemonCreate,
|
||||
PokemonResponse,
|
||||
PokemonUpdate,
|
||||
@@ -23,21 +24,35 @@ from app.schemas.pokemon import (
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/pokemon", response_model=list[PokemonResponse])
|
||||
@router.get("/pokemon", response_model=PaginatedPokemonResponse)
|
||||
async def list_pokemon(
|
||||
search: str | None = Query(None),
|
||||
limit: int = Query(50, ge=1, le=500),
|
||||
offset: int = Query(0, ge=0),
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
query = select(Pokemon)
|
||||
# Build base query with optional search filter
|
||||
base_query = select(Pokemon)
|
||||
if search:
|
||||
query = query.where(
|
||||
base_query = base_query.where(
|
||||
func.lower(Pokemon.name).contains(search.lower())
|
||||
)
|
||||
query = query.order_by(Pokemon.national_dex).offset(offset).limit(limit)
|
||||
result = await session.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
# Get total count
|
||||
count_query = select(func.count()).select_from(base_query.subquery())
|
||||
total = (await session.execute(count_query)).scalar() or 0
|
||||
|
||||
# Get paginated items
|
||||
items_query = base_query.order_by(Pokemon.national_dex).offset(offset).limit(limit)
|
||||
result = await session.execute(items_query)
|
||||
items = result.scalars().all()
|
||||
|
||||
return PaginatedPokemonResponse(
|
||||
items=items,
|
||||
total=total,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/pokemon/bulk-import", response_model=BulkImportResult)
|
||||
|
||||
@@ -11,6 +11,13 @@ class PokemonResponse(CamelModel):
|
||||
sprite_url: str | None
|
||||
|
||||
|
||||
class PaginatedPokemonResponse(CamelModel):
|
||||
items: list[PokemonResponse]
|
||||
total: int
|
||||
limit: int
|
||||
offset: int
|
||||
|
||||
|
||||
class EvolutionResponse(CamelModel):
|
||||
id: int
|
||||
from_pokemon_id: int
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -304,14 +304,23 @@ def process_version(version_name: str, vg_info: dict) -> list[dict]:
|
||||
return routes
|
||||
|
||||
|
||||
def fetch_pokemon_data(dex_numbers: set[int]) -> list[dict]:
|
||||
"""Fetch Pokemon name/type data for all collected dex numbers."""
|
||||
print(f"\n--- Fetching {len(dex_numbers)} Pokemon ---")
|
||||
def fetch_all_pokemon() -> list[dict]:
|
||||
"""Fetch all Pokemon species from the local PokeAPI data."""
|
||||
pokemon_dir = POKEAPI_DIR / "pokemon-species"
|
||||
|
||||
# Get all species IDs (directories with numeric names, excluding forms 10000+)
|
||||
all_species = []
|
||||
for entry in pokemon_dir.iterdir():
|
||||
if entry.is_dir() and entry.name.isdigit():
|
||||
dex = int(entry.name)
|
||||
if dex < 10000: # Exclude alternate forms
|
||||
all_species.append(dex)
|
||||
|
||||
all_species.sort()
|
||||
print(f"\n--- Fetching {len(all_species)} Pokemon species ---")
|
||||
|
||||
pokemon_list = []
|
||||
dex_sorted = sorted(dex_numbers)
|
||||
|
||||
for i, dex in enumerate(dex_sorted, 1):
|
||||
for i, dex in enumerate(all_species, 1):
|
||||
poke = load_resource("pokemon", dex)
|
||||
types = [t["type"]["name"] for t in poke["types"]]
|
||||
pokemon_list.append({
|
||||
@@ -321,8 +330,8 @@ def fetch_pokemon_data(dex_numbers: set[int]) -> list[dict]:
|
||||
"sprite_url": f"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{dex}.png",
|
||||
})
|
||||
|
||||
if i % 50 == 0 or i == len(dex_sorted):
|
||||
print(f" Fetched {i}/{len(dex_sorted)}")
|
||||
if i % 100 == 0 or i == len(all_species):
|
||||
print(f" Fetched {i}/{len(all_species)}")
|
||||
|
||||
return sorted(pokemon_list, key=lambda x: x["national_dex"])
|
||||
|
||||
@@ -512,13 +521,16 @@ def main():
|
||||
routes = process_version(ver_name, vg_info)
|
||||
write_json(f"{ver_name}.json", routes)
|
||||
|
||||
# Fetch all Pokemon data
|
||||
pokemon = fetch_pokemon_data(all_pokemon_dex)
|
||||
# Fetch all Pokemon species
|
||||
pokemon = fetch_all_pokemon()
|
||||
write_json("pokemon.json", pokemon)
|
||||
print(f"\nWrote {len(pokemon)} Pokemon to pokemon.json")
|
||||
|
||||
# Fetch evolution chains
|
||||
evolutions = fetch_evolution_data(all_pokemon_dex)
|
||||
# Build set of all seeded dex numbers for evolution filtering
|
||||
all_seeded_dex = {p["national_dex"] for p in pokemon}
|
||||
|
||||
# Fetch evolution chains for all seeded Pokemon
|
||||
evolutions = fetch_evolution_data(all_seeded_dex)
|
||||
apply_evolution_overrides(evolutions)
|
||||
write_json("evolutions.json", evolutions)
|
||||
print(f"\nWrote {len(evolutions)} evolution pairs to evolutions.json")
|
||||
|
||||
Reference in New Issue
Block a user