The field name 'date' in EventUpdate shadowed the 'date' type from datetime, causing Pydantic v2 to interpret Optional[date] as Optional[None] — rejecting all non-null values with a 422 error. Fix: rename import to 'date as _date' and use '_date' in all annotations. Also improve error handling in admin forms to properly display 422 validation error messages. Co-Authored-By: Claude <noreply@anthropic.com>
115 lines
2.5 KiB
Python
115 lines
2.5 KiB
Python
from datetime import date as _date
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel, computed_field, field_validator
|
|
|
|
|
|
# ── Program ──────────────────────────────────────────────
|
|
|
|
DAY_NAMES = {
|
|
1: "Monday",
|
|
2: "Tuesday",
|
|
3: "Wednesday",
|
|
4: "Thursday",
|
|
5: "Friday",
|
|
6: "Saturday",
|
|
7: "Sunday",
|
|
}
|
|
|
|
|
|
class ProgramCreate(BaseModel):
|
|
day_of_week: int
|
|
day_label: str
|
|
time: str
|
|
title: str
|
|
host: str
|
|
genre: str
|
|
|
|
|
|
class ProgramUpdate(BaseModel):
|
|
day_of_week: Optional[int] = None
|
|
day_label: Optional[str] = None
|
|
time: Optional[str] = None
|
|
title: Optional[str] = None
|
|
host: Optional[str] = None
|
|
genre: Optional[str] = None
|
|
|
|
|
|
class ProgramResponse(BaseModel):
|
|
id: int
|
|
day_of_week: int
|
|
time: str
|
|
title: str
|
|
host: str
|
|
genre: str
|
|
|
|
@computed_field
|
|
@property
|
|
def day_label(self) -> str:
|
|
return DAY_NAMES.get(self.day_of_week, "Unknown")
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
# ── Event ────────────────────────────────────────────────
|
|
|
|
class EventCreate(BaseModel):
|
|
date: _date
|
|
title: str
|
|
description: str
|
|
location: str
|
|
icon: str
|
|
rsvp_url: Optional[str] = None
|
|
|
|
|
|
class EventUpdate(BaseModel):
|
|
date: Optional[_date] = None
|
|
title: Optional[str] = None
|
|
description: Optional[str] = None
|
|
location: Optional[str] = None
|
|
icon: Optional[str] = None
|
|
rsvp_url: Optional[str] = None
|
|
active: Optional[bool] = None
|
|
|
|
|
|
class EventResponse(BaseModel):
|
|
id: int
|
|
date: _date
|
|
title: str
|
|
description: str
|
|
location: str
|
|
icon: str
|
|
rsvp_url: Optional[str]
|
|
active: bool
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
# ── DonationTier ─────────────────────────────────────────
|
|
|
|
class TierCreate(BaseModel):
|
|
name: str
|
|
amount: float
|
|
icon: str
|
|
benefits: list[str]
|
|
display_order: int
|
|
|
|
|
|
class TierUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
amount: Optional[float] = None
|
|
icon: Optional[str] = None
|
|
benefits: Optional[list[str]] = None
|
|
display_order: Optional[int] = None
|
|
|
|
|
|
class TierResponse(BaseModel):
|
|
id: int
|
|
name: str
|
|
amount: float
|
|
icon: str
|
|
benefits: list[str]
|
|
display_order: int
|
|
|
|
model_config = {"from_attributes": True}
|