[lifeevents] Add life events to scrobbles

This commit is contained in:
2024-05-23 00:14:06 -04:00
parent 8ed0bd3d21
commit e15d253d58
12 changed files with 218 additions and 0 deletions

View File

@ -0,0 +1,16 @@
from django.contrib import admin
from lifeevents.models import LifeEvent
from scrobbles.admin import ScrobbleInline
@admin.register(LifeEvent)
class EventAdmin(admin.ModelAdmin):
date_hierarchy = "created"
list_display = ("title",)
search_fields = ("title",)
ordering = ("-created",)
inlines = [
ScrobbleInline,
]

View File

@ -0,0 +1,79 @@
# Generated by Django 4.2.11 on 2024-05-07 13:37
from django.db import migrations, models
import django_extensions.db.fields
import taggit.managers
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
("scrobbles", "0055_rename_scrobble_log_scrobble_log"),
]
operations = [
migrations.CreateModel(
name="LifeEvent",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created",
django_extensions.db.fields.CreationDateTimeField(
auto_now_add=True, verbose_name="created"
),
),
(
"modified",
django_extensions.db.fields.ModificationDateTimeField(
auto_now=True, verbose_name="modified"
),
),
(
"uuid",
models.UUIDField(
blank=True,
default=uuid.uuid4,
editable=False,
null=True,
),
),
(
"title",
models.CharField(blank=True, max_length=255, null=True),
),
(
"run_time_seconds",
models.IntegerField(blank=True, null=True),
),
(
"run_time_ticks",
models.PositiveBigIntegerField(blank=True, null=True),
),
("description", models.TextField(blank=True, null=True)),
(
"genre",
taggit.managers.TaggableManager(
blank=True,
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
],
options={
"abstract": False,
},
),
]

View File

@ -0,0 +1,39 @@
from django.apps import apps
from django.db import models
from django.urls import reverse
import pendulum
from lifeevents.dataclasses import LifeEventMetadata
from scrobbles.mixins import ScrobblableMixin
BNULL = {"blank": True, "null": True}
class LifeEvent(ScrobblableMixin):
COMPLETION_PERCENT = 100
description = models.TextField(**BNULL)
def get_absolute_url(self):
return reverse(
"life-events:life-event_detail", kwargs={"slug": self.uuid}
)
@property
def metadata_class(self):
return LifeEventMetadata
@classmethod
def find_or_create(cls, title: str) -> "LifeEvent":
return cls.objects.filter(title=title).first()
def scrobble_for_user(self, user_id):
Scrobble = apps.get_model("scrobbles", "Scrobble")
return Scrobble.objects.create(
user_id=user_id, life_event=self, timestamp=pendulum.now()
)
def scrobbles(self, user_id):
Scrobble = apps.get_model("scrobbles", "Scrobble")
return Scrobble.objects.filter(
user_id=user_id, life_event=self
).order_by("-timestamp")

View File

@ -0,0 +1,14 @@
from django.urls import path
from lifeevents import views
app_name = "events"
urlpatterns = [
path("events/", views.EventListView.as_view(), name="event_list"),
path(
"event/<slug:slug>/",
views.EventDetailView.as_view(),
name="event_detail",
),
]

View File

@ -0,0 +1,12 @@
from django.views import generic
from lifeevents.models import LifeEvent
class EventListView(generic.ListView):
model = LifeEvent
paginate_by = 20
class EventDetailView(generic.DetailView):
model = LifeEvent
slug_field = "uuid"

View File

@ -24,6 +24,7 @@ class ScrobbleInline(admin.TabularInline):
"board_game",
"geo_location",
"web_page",
"life_event",
"user",
)
exclude = (
@ -118,6 +119,7 @@ class ScrobbleAdmin(admin.ModelAdmin):
"board_game",
"geo_location",
"web_page",
"life_event",
)
list_filter = (
"is_paused",

View File

@ -0,0 +1,45 @@
# Generated by Django 4.2.11 on 2024-05-07 13:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("lifeevents", "0001_initial"),
("scrobbles", "0055_rename_scrobble_log_scrobble_log"),
]
operations = [
migrations.AddField(
model_name="scrobble",
name="life_event",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
to="lifeevents.lifeevent",
),
),
migrations.AlterField(
model_name="scrobble",
name="media_type",
field=models.CharField(
choices=[
("Video", "Video"),
("Track", "Track"),
("PodcastEpisode", "Podcast episode"),
("SportEvent", "Sport event"),
("Book", "Book"),
("VideoGame", "Video game"),
("BoardGame", "Board game"),
("GeoLocation", "GeoLocation"),
("WebPage", "Web Page"),
("LifeEvent", "Life event"),
],
default="Video",
max_length=14,
),
),
]

View File

@ -39,6 +39,7 @@ from videogames import retroarch
from videogames.models import VideoGame
from videos.models import Series, Video
from webpages.models import WebPage
from lifeevents.models import LifeEvent
from vrobbler.apps.scrobbles.constants import MEDIA_END_PADDING_SECONDS
@ -481,6 +482,7 @@ class Scrobble(TimeStampedModel):
BOARD_GAME = "BoardGame", "Board game"
GEO_LOCATION = "GeoLocation", "GeoLocation"
WEBPAGE = "WebPage", "Web Page"
LIFE_EVENT = "LifeEvent", "Life event"
uuid = models.UUIDField(editable=False, **BNULL)
video = models.ForeignKey(Video, on_delete=models.DO_NOTHING, **BNULL)
@ -502,6 +504,9 @@ class Scrobble(TimeStampedModel):
GeoLocation, on_delete=models.DO_NOTHING, **BNULL
)
web_page = models.ForeignKey(WebPage, on_delete=models.DO_NOTHING, **BNULL)
life_event = models.ForeignKey(
LifeEvent, on_delete=models.DO_NOTHING, **BNULL
)
media_type = models.CharField(
max_length=14, choices=MediaType.choices, default=MediaType.VIDEO
)
@ -809,6 +814,8 @@ class Scrobble(TimeStampedModel):
media_obj = self.geo_location
if self.web_page:
media_obj = self.web_page
if self.life_event:
media_obj = self.life_event
return media_obj
def __str__(self):

View File

@ -110,6 +110,7 @@ INSTALLED_APPS = [
"videogames",
"locations",
"webpages",
"lifeevents",
"mathfilters",
"rest_framework",
"allauth",

View File

@ -124,6 +124,7 @@ INSTALLED_APPS = [
"videogames",
"locations",
"webpages",
"lifeevents",
"mathfilters",
"rest_framework",
"allauth",

View File

@ -11,6 +11,7 @@ from vrobbler.apps.podcasts import urls as podcast_urls
from vrobbler.apps.videogames import urls as videogame_urls
from vrobbler.apps.boardgames import urls as boardgame_urls
from vrobbler.apps.locations import urls as locations_urls
from vrobbler.apps.lifeevents import urls as lifeevents_urls
from vrobbler.apps.webpages import urls as webpages_urls
from vrobbler.apps.music.api.views import (
AlbumViewSet,
@ -71,6 +72,7 @@ urlpatterns = [
path("", include(locations_urls, namespace="locations")),
path("", include(webpages_urls, namespace="webpages")),
path("", include(podcast_urls, namespace="podcasts")),
path("", include(lifeevents_urls, namespace="life-events")),
path("", include(scrobble_urls, namespace="scrobbles")),
path(
"", scrobbles_views.RecentScrobbleList.as_view(), name="vrobbler-home"