Add genres!

This commit is contained in:
2023-03-14 18:35:58 -04:00
parent c9b04772a0
commit c9874b3fda
13 changed files with 354 additions and 5 deletions

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("books", "0010_rename_run_time_book_run_time_seconds"),
]
operations = [
migrations.AddField(
model_name="book",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("music", "0016_rename_run_time_track_run_time_seconds"),
]
operations = [
migrations.AddField(
model_name="track",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("podcasts", "0007_rename_run_time_episode_run_time_seconds"),
]
operations = [
migrations.AddField(
model_name="episode",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -6,6 +6,7 @@ from scrobbles.models import (
LastFmImport,
Scrobble,
)
from scrobbles.mixins import Genre
class ScrobbleInline(admin.TabularInline):
@ -49,6 +50,14 @@ class KoReaderImportAdmin(ImportBaseAdmin):
""""""
@admin.register(Genre)
class GenreAdmin(admin.ModelAdmin):
list_display = (
"name",
"source",
)
@admin.register(ChartRecord)
class ChartRecordAdmin(admin.ModelAdmin):
date_hierarchy = "created"

View File

@ -0,0 +1,92 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
(
"scrobbles",
"0032_rename_playback_position_scrobble_playback_position_seconds",
),
]
operations = [
migrations.CreateModel(
name="Genre",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"name",
models.CharField(
max_length=100, unique=True, verbose_name="name"
),
),
(
"slug",
models.SlugField(
max_length=100, unique=True, verbose_name="slug"
),
),
(
"source",
models.CharField(blank=True, max_length=255, null=True),
),
],
options={
"verbose_name": "Genre",
"verbose_name_plural": "Genres",
},
),
migrations.CreateModel(
name="ObjectWithGenres",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"object_id",
models.IntegerField(
db_index=True, verbose_name="object ID"
),
),
(
"content_type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="%(app_label)s_%(class)s_tagged_items",
to="contenttypes.contenttype",
verbose_name="content type",
),
),
(
"tag",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="%(app_label)s_%(class)s_items",
to="scrobbles.genre",
),
),
],
options={
"abstract": False,
},
),
]

View File

@ -5,13 +5,31 @@ from uuid import uuid4
from django.db import models
from django.urls import reverse
from django_extensions.db.models import TimeStampedModel
from taggit.managers import TaggableManager
from scrobbles.utils import get_scrobbles_for_media
from taggit.models import TagBase, GenericTaggedItemBase
BNULL = {"blank": True, "null": True}
logger = logging.getLogger(__name__)
class Genre(TagBase):
source = models.CharField(max_length=255, **BNULL)
class Meta:
verbose_name = "Genre"
verbose_name_plural = "Genres"
class ObjectWithGenres(GenericTaggedItemBase):
tag = models.ForeignKey(
Genre,
on_delete=models.CASCADE,
related_name="%(app_label)s_%(class)s_items",
)
class ScrobblableMixin(TimeStampedModel):
SECONDS_TO_STALE = 1600
@ -20,6 +38,8 @@ class ScrobblableMixin(TimeStampedModel):
run_time_seconds = models.IntegerField(**BNULL)
run_time_ticks = models.PositiveBigIntegerField(**BNULL)
genre = TaggableManager(through=ObjectWithGenres)
class Meta:
abstract = True

View File

@ -5,7 +5,6 @@ from typing import Optional
from uuid import uuid4
from books.models import Book
from django.apps import apps
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("sports", "0012_sport_default_event_run_time_seconds"),
]
operations = [
migrations.AddField(
model_name="sportevent",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("videogames", "0008_rename_run_time_videogame_run_time_seconds"),
]
operations = [
migrations.AddField(
model_name="videogame",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 4.1.5 on 2023-03-14 19:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"videos",
"0009_rename_overview_series_plot_remove_series_tagline_and_more",
),
]
operations = [
migrations.RenameField(
model_name="series",
old_name="genres",
new_name="tags",
),
migrations.AlterField(
model_name="video",
name="cover_image",
field=models.ImageField(
blank=True, null=True, upload_to="videos/video/"
),
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 4.1.5 on 2023-03-14 19:42
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
("videos", "0010_rename_genres_series_tags_alter_video_cover_image"),
]
operations = [
migrations.AddField(
model_name="video",
name="tags",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="taggit.TaggedItem",
to="taggit.Tag",
verbose_name="Tags",
),
),
]

View File

@ -0,0 +1,43 @@
# Generated by Django 4.1.5 on 2023-03-14 22:27
from django.db import migrations
import taggit.managers
class Migration(migrations.Migration):
dependencies = [
("scrobbles", "0033_genre_objectwithgenres"),
("videos", "0011_video_tags"),
]
operations = [
migrations.RemoveField(
model_name="series",
name="tags",
),
migrations.RemoveField(
model_name="video",
name="tags",
),
migrations.AddField(
model_name="series",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
migrations.AddField(
model_name="video",
name="genre",
field=taggit.managers.TaggableManager(
help_text="A comma-separated list of tags.",
through="scrobbles.ObjectWithGenres",
to="scrobbles.Genre",
verbose_name="Tags",
),
),
]

View File

@ -9,8 +9,7 @@ from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_extensions.db.models import TimeStampedModel
from scrobbles.mixins import ScrobblableMixin
from scrobbles.utils import convert_to_seconds
from scrobbles.mixins import ObjectWithGenres, ScrobblableMixin
from taggit.managers import TaggableManager
from videos.imdb import lookup_video_from_imdb
@ -27,7 +26,7 @@ class Series(TimeStampedModel):
imdb_rating = models.FloatField(**BNULL)
cover_image = models.ImageField(upload_to="videos/series/", **BNULL)
genres = TaggableManager()
genre = TaggableManager(through=ObjectWithGenres)
class Meta:
verbose_name_plural = "series"
@ -49,7 +48,10 @@ class Series(TimeStampedModel):
).order_by("-timestamp")
def fix_metadata(self, force_update=False):
imdb_dict = lookup_video_from_imdb(self.name, kind="tv series")
name_or_id = self.name
if self.imdb_id:
name_or_id = self.imdb_id
imdb_dict = lookup_video_from_imdb(name_or_id)
if not imdb_dict:
logger.warn(f"No imdb data for {self}")
return
@ -67,6 +69,9 @@ class Series(TimeStampedModel):
fname = f"{self.name}_{self.uuid}.jpg"
self.cover_image.save(fname, ContentFile(r.content), save=True)
if genres := imdb_dict.data.get("genres"):
self.genre.add(*genres)
class Video(ScrobblableMixin):
COMPLETION_PERCENT = getattr(settings, "VIDEO_COMPLETION_PERCENT", 90)
@ -149,6 +154,9 @@ class Video(ScrobblableMixin):
fname = f"{self.title}_{self.uuid}.jpg"
self.cover_image.save(fname, ContentFile(r.content), save=True)
if genres := imdb_dict.data.get("genres"):
self.genre.add(*genres)
@classmethod
def find_or_create(cls, data_dict: Dict) -> "Video":
"""Given a data dict from Jellyfin, does the heavy lifting of looking up