import logging from dataclasses import dataclass from enum import IntEnum from typing import Optional from uuid import uuid4 from django.contrib.auth import get_user_model from django.db import models from django.urls import reverse from imagekit.models import ImageSpecField from imagekit.processors import ResizeToFit from scrobbles.dataclasses import BaseLogData from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin logger = logging.getLogger(__name__) BNULL = {"blank": True, "null": True} User = get_user_model() class MoodType(models.TextChoices): POSITIVE = "positive", "Positive" NEGATIVE = "negative", "Negative" class MoodQuality(IntEnum): VERY_UNPLEASANT = 1 UNPLEASANT = 2 SLIGHTLY_UNPLEASANT = 3 NEUTRAL = 4 SLIGHTLY_PLEASANT = 5 PLEASANT = 6 VERY_PLEASANT = 7 @dataclass class MoodLogData(BaseLogData): mood_type: Optional[str] = None mood_reason_ids: Optional[list[int]] = None mood_quality: Optional[int] = None weather_temp: Optional[float] = None weather_description: Optional[str] = None @classmethod def override_fields(cls) -> dict: from django import forms from moods.models import MoodReason return { "mood_type": forms.ChoiceField( choices=MoodType.choices, required=False, widget=forms.Select(attrs={"class": "form-control"}), ), "mood_reason_ids": forms.ModelMultipleChoiceField( queryset=MoodReason.objects.all().order_by("title"), required=False, widget=forms.SelectMultiple(attrs={"size": 10}), ), "mood_quality": forms.ChoiceField( choices=[ (mq.value, mq.name.replace("_", " ").title()) for mq in MoodQuality ], required=False, widget=forms.Select(attrs={"class": "form-control"}), ), } class Mood(ScrobblableMixin): description = models.TextField(**BNULL) image = models.ImageField(upload_to="moods/", **BNULL) image_small = ImageSpecField( source="thumbnail", processors=[ResizeToFit(100, 100)], format="JPEG", options={"quality": 60}, ) image_medium = ImageSpecField( source="thumbnail", processors=[ResizeToFit(300, 300)], format="JPEG", options={"quality": 75}, ) mood_type = models.CharField( max_length=20, choices=MoodType.choices, **BNULL ) def __str__(self): if self.title: return self.title return str(self.uuid) def get_absolute_url(self): return reverse("moods:mood_detail", kwargs={"slug": self.uuid}) @property def subtitle(self) -> str: return "" @property def strings(self) -> ScrobblableConstants: return ScrobblableConstants(verb="Feeling", tags="thinking") @property def logdata_cls(self): return MoodLogData @property def primary_image_url(self) -> str: if self.image: return self.image.url return "" class MoodReason(models.Model): uuid = models.UUIDField(default=uuid4, editable=False, **BNULL) title = models.CharField(max_length=255, **BNULL) description = models.TextField(**BNULL) def __str__(self): return self.title