lib.itmens/music/models.py

271 lines
7.9 KiB
Python
Raw Normal View History

2021-02-12 19:23:23 +01:00
import uuid
import django.contrib.postgres.fields as postgres
2021-12-24 11:56:04 -08:00
from django.utils.translation import gettext_lazy as _
2021-02-12 19:23:23 +01:00
from django.db import models
from django.core.serializers.json import DjangoJSONEncoder
from django.shortcuts import reverse
from common.models import Entity, Mark, Review, Tag, SourceSiteEnum, MarkStatusEnum
2021-08-01 12:36:03 +02:00
from common.utils import ChoicesDictGenerator, GenerateDateUUIDMediaFilePath
2021-02-12 19:23:23 +01:00
from django.utils import timezone
from django.conf import settings
2022-09-08 19:41:56 -04:00
from simple_history.models import HistoricalRecords
2021-02-12 19:23:23 +01:00
MusicMarkStatusTranslation = {
MarkStatusEnum.DO.value: _("在听"),
MarkStatusEnum.WISH.value: _("想听"),
MarkStatusEnum.COLLECT.value: _("听过")
}
2021-02-12 19:23:23 +01:00
def song_cover_path(instance, filename):
return GenerateDateUUIDMediaFilePath(instance, filename, settings.SONG_MEDIA_PATH_ROOT)
2021-02-12 19:23:23 +01:00
def album_cover_path(instance, filename):
return GenerateDateUUIDMediaFilePath(instance, filename, settings.ALBUM_MEDIA_PATH_ROOT)
2021-02-12 19:23:23 +01:00
class Album(Entity):
title = models.CharField(_("标题"), max_length=500)
release_date = models.DateField(
_('发行日期'), auto_now=False, auto_now_add=False, null=True, blank=True)
cover = models.ImageField(
_("封面"), upload_to=album_cover_path, default=settings.DEFAULT_ALBUM_IMAGE, blank=True)
2021-02-12 19:23:23 +01:00
duration = models.PositiveIntegerField(_("时长"), null=True, blank=True)
artist = postgres.ArrayField(
models.CharField(_("artist"), blank=True,
2022-06-17 13:57:32 -04:00
default='', max_length=200),
2021-02-12 19:23:23 +01:00
null=True,
blank=True,
default=list,
verbose_name=_("艺术家")
)
genre = models.CharField(_("流派"), blank=True,
default='', max_length=100)
company = postgres.ArrayField(
models.CharField(blank=True,
2021-02-15 21:27:50 +01:00
default='', max_length=500),
2021-02-12 19:23:23 +01:00
null=True,
blank=True,
default=list,
verbose_name=_("发行方")
)
track_list = models.TextField(_("曲目"), blank=True, default="")
2022-09-08 19:41:56 -04:00
history = HistoricalRecords()
@property
def year(self):
return self.release_date.year if self.release_date else None
2021-02-12 19:23:23 +01:00
def __str__(self):
return self.title
2022-02-20 19:09:23 -05:00
def get_json(self):
r = {
'artist': self.artist,
'release_date': self.release_date,
'genre': self.genre,
'publisher': self.company,
}
r.update(super().get_json())
return r
2021-09-22 21:17:13 -04:00
def get_embed_link(self):
if self.source_site == SourceSiteEnum.SPOTIFY.value:
return self.source_url.replace("open.spotify.com/", "open.spotify.com/embed/")
2021-12-16 23:21:23 -05:00
elif self.source_site == SourceSiteEnum.BANDCAMP.value and self.other_info and 'bandcamp_album_id' in self.other_info:
return f"https://bandcamp.com/EmbeddedPlayer/album={self.other_info['bandcamp_album_id']}/size=large/bgcol=ffffff/linkcol=19A2CA/artwork=small/transparent=true/"
else:
return None
2021-09-22 21:17:13 -04:00
2021-02-12 19:23:23 +01:00
def get_absolute_url(self):
return reverse("music:retrieve_album", args=[self.id])
2022-06-12 11:29:05 -04:00
@property
def wish_url(self):
return reverse("music:wish_album", args=[self.id])
2021-02-12 19:23:23 +01:00
def get_tags_manager(self):
return self.album_tags
@property
def verbose_category_name(self):
return _("专辑")
@property
def mark_class(self):
return AlbumMark
2022-05-01 18:13:09 -04:00
@property
def tag_class(self):
return AlbumTag
2021-02-12 19:23:23 +01:00
class Song(Entity):
'''
Song(track) entity, can point to entity Album
'''
title = models.CharField(_("标题"), max_length=500)
release_date = models.DateField(_('发行日期'), auto_now=False, auto_now_add=False, null=True, blank=True)
isrc = models.CharField(_("ISRC"),
blank=True, max_length=15, db_index=True, default='')
# duration in ms
duration = models.PositiveIntegerField(_("时长"), null=True, blank=True)
cover = models.ImageField(
_("封面"), upload_to=song_cover_path, default=settings.DEFAULT_SONG_IMAGE, blank=True)
2021-02-12 19:23:23 +01:00
artist = postgres.ArrayField(
models.CharField(blank=True,
default='', max_length=100),
null=True,
blank=True,
default=list,
verbose_name=_("艺术家")
)
genre = models.CharField(_("流派"), blank=True, default='', max_length=100)
album = models.ForeignKey(
2021-02-15 21:27:50 +01:00
Album, models.SET_NULL, "album_songs", null=True, blank=True, verbose_name=_("所属专辑"))
2021-02-12 19:23:23 +01:00
2022-09-08 19:41:56 -04:00
history = HistoricalRecords()
2021-02-12 19:23:23 +01:00
def __str__(self):
return self.title
2022-02-20 19:09:23 -05:00
def get_json(self):
r = {
'artist': self.artist,
'release_date': self.release_date,
'genre': self.genre,
}
r.update(super().get_json())
return r
2021-09-22 21:17:13 -04:00
def get_embed_link(self):
return self.source_url.replace("open.spotify.com/", "open.spotify.com/embed/") if self.source_site == SourceSiteEnum.SPOTIFY.value else None
2021-02-12 19:23:23 +01:00
def get_absolute_url(self):
return reverse("music:retrieve_song", args=[self.id])
2022-06-12 11:29:05 -04:00
@property
def wish_url(self):
return reverse("music:wish_song", args=[self.id])
2021-02-12 19:23:23 +01:00
def get_tags_manager(self):
return self.song_tags
2021-02-12 19:23:23 +01:00
@property
def verbose_category_name(self):
return _("单曲")
@property
def mark_class(self):
return SongMark
2022-05-01 18:13:09 -04:00
@property
def tag_class(self):
return SongTag
2021-02-12 19:23:23 +01:00
class SongMark(Mark):
song = models.ForeignKey(
Song, on_delete=models.CASCADE, related_name='song_marks', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['owner', 'song'], name='unique_song_mark')
]
@property
def translated_status(self):
return MusicMarkStatusTranslation[self.status]
2021-02-12 19:23:23 +01:00
class SongReview(Review):
song = models.ForeignKey(
Song, on_delete=models.CASCADE, related_name='song_reviews', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['owner', 'song'], name='unique_song_review')
]
@property
def url(self):
2022-05-29 10:04:26 -04:00
return settings.APP_WEBSITE + reverse("music:retrieve_song_review", args=[self.id])
2022-08-20 00:14:18 -04:00
@property
def item(self):
return self.song
2021-02-12 19:23:23 +01:00
class SongTag(Tag):
song = models.ForeignKey(
Song, on_delete=models.CASCADE, related_name='song_tags', null=True)
mark = models.ForeignKey(
SongMark, on_delete=models.CASCADE, related_name='songmark_tags', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['content', 'mark'], name="unique_songmark_tag")
]
2022-04-25 22:40:09 -04:00
@property
def item(self):
return self.song
2021-02-12 19:23:23 +01:00
class AlbumMark(Mark):
album = models.ForeignKey(
Album, on_delete=models.CASCADE, related_name='album_marks', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['owner', 'album'], name='unique_album_mark')
]
@property
def translated_status(self):
return MusicMarkStatusTranslation[self.status]
2021-02-12 19:23:23 +01:00
class AlbumReview(Review):
album = models.ForeignKey(
Album, on_delete=models.CASCADE, related_name='album_reviews', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['owner', 'album'], name='unique_album_review')
]
@property
def url(self):
2022-05-29 10:04:26 -04:00
return settings.APP_WEBSITE + reverse("music:retrieve_album_review", args=[self.id])
2022-08-20 00:14:18 -04:00
@property
def item(self):
return self.album
2021-02-12 19:23:23 +01:00
class AlbumTag(Tag):
album = models.ForeignKey(
Album, on_delete=models.CASCADE, related_name='album_tags', null=True)
mark = models.ForeignKey(
AlbumMark, on_delete=models.CASCADE, related_name='albummark_tags', null=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['content', 'mark'], name="unique_albummark_tag")
]
2022-04-25 22:40:09 -04:00
@property
def item(self):
return self.album