Files
DanceVideos/app/playlists/playlist_model.py
2025-10-16 17:18:58 +02:00

108 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# playlists/playlist_model.py
from pydantic import BaseModel, Field, validator, field_validator
from typing import List, Optional, Literal
from datetime import date, datetime
import json
import db
from typing import Optional, List, Literal
from pydantic import BaseModel, Field
import json
class RuleSet(BaseModel):
include_labels: List[str] = []
exclude_labels: List[str] = []
include_playlists: List[int] = []
exclude_playlists: List[int] = []
date_after: Optional[str] = None
date_before: Optional[str] = None
date_delta_days: Optional[int] = None
difficulty: Optional[str] = None
day_of_week: Optional[str] = None
address_keyword: Optional[str] = None
label_logic: Literal["AND", "OR"] = "AND"
logic: Literal["AND", "OR"] = "AND"
# --- Normalisation des dates (entrée) ---
@field_validator("date_after", "date_before", mode="before")
def normalize_date(cls, v):
"""Convertit automatiquement date/datetime en str ISO avant stockage."""
if isinstance(v, (date, datetime)):
return v.isoformat()
return v
def model_dump(self, *args, **kwargs):
"""Force la sortie JSON-safe (dates converties en str)."""
data = super().model_dump(*args, **kwargs)
for key in ["date_after", "date_before"]:
v = data.get(key)
if isinstance(v, (date, datetime)):
data[key] = v.isoformat()
return data
@validator("date_after", "date_before", pre=True, always=True)
def convert_date(cls, v):
"""Convertit automatiquement les objets date/datetime en ISO string."""
if isinstance(v, (date, datetime)):
return v.isoformat()
return v
def dict(self, *args, **kwargs):
"""Sassure que toutes les dates sont des chaînes sérialisables."""
data = super().dict(*args, **kwargs)
for key in ["date_after", "date_before"]:
v = data.get(key)
if isinstance(v, (date, datetime)):
data[key] = v.isoformat()
return data
def to_json(self) -> str:
return json.dumps(self.dict(), ensure_ascii=False, indent=2)
@classmethod
def from_json(cls, raw):
if not raw:
return cls()
if isinstance(raw, dict):
return cls(**raw)
try:
return cls(**json.loads(raw))
except Exception:
return cls()
class Playlist(BaseModel):
id: Optional[int] = None
name: str
description: Optional[str] = ""
type: Literal["manual", "dynamic"] = "manual"
rules: RuleSet = Field(default_factory=RuleSet)
created_at: Optional[str] = None
updated_at: Optional[str] = None
@validator("rules", pre=True, always=True)
def ensure_rules(cls, v):
"""Transforme la valeur de rules_json (None, str ou dict) en RuleSet."""
if isinstance(v, RuleSet):
return v
return RuleSet.from_json(v)
def save(self):
"""Insert or update playlist"""
with db.get_conn() as conn:
cur = conn.cursor()
if self.id:
cur.execute("""
UPDATE playlists
SET name=?, description=?, type=?, rules_json=?, updated_at=CURRENT_TIMESTAMP
WHERE id=?
""", (self.name, self.description, self.type, self.rules.to_json(), self.id))
else:
cur.execute("""
INSERT INTO playlists (name, description, type, rules_json)
VALUES (?, ?, ?, ?)
""", (self.name, self.description, self.type, self.rules.to_json()))
self.id = cur.lastrowid
conn.commit()