import json from dataclasses import asdict, dataclass from typing import Optional from dataclass_wizard import JSONWizard from django import forms from django.contrib.auth import get_user_model from people.models import Person from scrobbles.forms import form_from_dataclass User = get_user_model() class ScrobbleLogDataEncoder(json.JSONEncoder): def default(self, o): return o.__dict__ class ScrobbleLogDataDecoder(json.JSONDecoder): def default(self, o): return o.__dict__ class JSONDataclass(JSONWizard): @property def asdict(self): return asdict(self) @property def json(self): return json.dumps(self.asdict) @dataclass class BaseLogData(JSONDataclass): description: Optional[str] = None notes: Optional[list[str]] = None _excluded_fields = {} @classmethod def form(cls): return form_from_dataclass(cls) @classmethod def override_fields(cls) -> dict: return {} @dataclass class LongPlayLogData(JSONDataclass): long_play_complete: bool = False @dataclass class WithPeopleLogData(JSONDataclass): with_people_ids: Optional[list[int]] = None @property def with_people(self) -> list["Person"]: from people.models import Person if not self.with_people_ids: return [] return [ Person.objects.filter(id=pid).first() for pid in self.with_people_ids ] @classmethod def override_fields(cls) -> dict: fields = {} for base in cls.mro()[1:]: if hasattr(base, "override_fields"): base_fields = base.override_fields() fields.update(base_fields) custom_fields = { "with_people_ids": forms.ModelMultipleChoiceField( queryset=Person.objects.all(), required=False, widget=forms.SelectMultiple(attrs={"size": 10}), ) } fields.update(custom_fields) return fields