Files
weather-fetch-lab/db_models.py
T

82 lines
2.6 KiB
Python
Raw Normal View History

2026-09-28 17:10:20 +03:00
import datetime
from collections.abc import Sequence
from dataclasses import dataclass
from sqlalchemy import Date, DateTime, Float, Integer, String, UniqueConstraint, select
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
from sqlalchemy.sql import func
class Base(DeclarativeBase):
pass
class WeatherForecast(Base):
__tablename__ = "weather_forecast"
__table_args__ = (
UniqueConstraint("city", "forecast_date", name="unique_city_forecast_date"),
)
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
city: Mapped[str] = mapped_column(String, nullable=False)
forecast_date: Mapped[datetime.date] = mapped_column(Date, nullable=False)
temp_min: Mapped[float] = mapped_column(Float, nullable=False)
temp_max: Mapped[float] = mapped_column(Float, nullable=False)
humidity: Mapped[int] = mapped_column(Integer, nullable=False)
wind_speed: Mapped[float] = mapped_column(Float, nullable=False)
description: Mapped[str | None] = mapped_column(String, nullable=True)
created_at: Mapped[datetime.datetime] = mapped_column(
DateTime, default=func.now(), nullable=False
)
def __repr__(self) -> str:
return (
f"WeatherForecast(id={self.id!r}, city={self.city!r}, "
f"forecast_date={self.forecast_date!r}, temp_min={self.temp_min!r}, "
f"temp_max={self.temp_max!r}, humidity={self.humidity!r}, "
f"wind_speed={self.wind_speed!r}, description={self.description!r})"
)
@dataclass(frozen=True)
class DailyForecast:
city: str
forecast_date: datetime.date
temp_min: float
temp_max: float
humidity: int
wind_speed: float
description: str
def save_forecasts(session: Session, forecasts: Sequence[DailyForecast]) -> int:
if not forecasts:
return 0
known: dict[str, set[datetime.date]] = {}
for city in {f.city for f in forecasts}:
known[city] = set(
session.scalars(
select(WeatherForecast.forecast_date).where(
WeatherForecast.city == city
)
).all()
)
add = [
WeatherForecast(
city=f.city,
forecast_date=f.forecast_date,
temp_min=f.temp_min,
temp_max=f.temp_max,
humidity=f.humidity,
wind_speed=f.wind_speed,
description=f.description,
)
for f in forecasts
if f.forecast_date not in known[f.city]
]
session.add_all(add)
session.commit()
return len(add)