song->album; refactor shelf
This commit is contained in:
parent
f24df6c0fd
commit
bde7ce47a3
7 changed files with 261 additions and 203 deletions
|
@ -65,7 +65,7 @@ def query_item_category(item_category):
|
|||
# return q
|
||||
ct = all_content_types()
|
||||
contenttype_ids = [ct[cls] for cls in classes]
|
||||
return Q(item__polymorphic_ctype__in=sorted(contenttype_ids))
|
||||
return Q(item__polymorphic_ctype__in=contenttype_ids)
|
||||
|
||||
|
||||
class Piece(PolymorphicModel, UserOwnedObjectMixin):
|
||||
|
@ -325,6 +325,9 @@ class List(Piece):
|
|||
def recent_members(self):
|
||||
return self.members.all().order_by("-created_time")
|
||||
|
||||
def get_members_in_category(self, item_category):
|
||||
return self.members.all().filter(query_item_category(item_category))
|
||||
|
||||
def get_member_for_item(self, item):
|
||||
return self.members.filter(item=item).first()
|
||||
|
||||
|
@ -459,44 +462,16 @@ class ShelfMember(ListMember):
|
|||
|
||||
class Shelf(List):
|
||||
class Meta:
|
||||
unique_together = [["owner", "item_category", "shelf_type"]]
|
||||
unique_together = [["owner", "shelf_type"]]
|
||||
|
||||
MEMBER_CLASS = ShelfMember
|
||||
items = models.ManyToManyField(Item, through="ShelfMember", related_name="+")
|
||||
item_category = models.CharField(
|
||||
choices=ItemCategory.choices, max_length=100, null=False, blank=False
|
||||
)
|
||||
shelf_type = models.CharField(
|
||||
choices=ShelfType.choices, max_length=100, null=False, blank=False
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.id} {self.title}"
|
||||
|
||||
@cached_property
|
||||
def item_category_label(self):
|
||||
return ItemCategory(self.item_category).label
|
||||
|
||||
@cached_property
|
||||
def shelf_label(self):
|
||||
return next(
|
||||
iter(
|
||||
[
|
||||
n[2]
|
||||
for n in iter(ShelfTypeNames)
|
||||
if n[0] == self.item_category and n[1] == self.shelf_type
|
||||
]
|
||||
),
|
||||
self.shelf_type,
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def title(self):
|
||||
q = _("{shelf_label}的{item_category}").format(
|
||||
shelf_label=self.shelf_label, item_category=self.item_category_label
|
||||
)
|
||||
return q
|
||||
# return _("{user}'s {shelf_name}").format(user=self.owner.mastodon_username, shelf_name=q)
|
||||
return f"{self.id} [{self.owner} {self.shelf_type} list]"
|
||||
|
||||
|
||||
class ShelfLogEntry(models.Model):
|
||||
|
@ -526,39 +501,31 @@ class ShelfManager:
|
|||
|
||||
def __init__(self, user):
|
||||
self.owner = user
|
||||
qs = Shelf.objects.filter(owner=self.owner)
|
||||
self.shelf_list = {v.shelf_type: v for v in qs}
|
||||
if len(self.shelf_list) == 0:
|
||||
self.initialize()
|
||||
|
||||
def initialize(self):
|
||||
for ic in ItemCategory:
|
||||
for qt in ShelfType:
|
||||
Shelf.objects.create(owner=self.owner, item_category=ic, shelf_type=qt)
|
||||
self.shelf_list[qt] = Shelf.objects.create(owner=self.owner, shelf_type=qt)
|
||||
|
||||
def _shelf_member_for_item(self, item):
|
||||
def locate_item(self, item) -> ShelfMember:
|
||||
return ShelfMember.objects.filter(
|
||||
item=item, parent__in=self.owner.shelf_set.all()
|
||||
item=item, parent__in=list(self.shelf_list.values())
|
||||
).first()
|
||||
|
||||
def _shelf_for_item_and_type(self, item, shelf_type):
|
||||
if not item or not shelf_type:
|
||||
return None
|
||||
return self.owner.shelf_set.all().filter(
|
||||
item_category=item.category, shelf_type=shelf_type
|
||||
)
|
||||
|
||||
def locate_item(self, item):
|
||||
member = ShelfMember.objects.filter(owner=self.owner, item=item).first()
|
||||
return member # .parent if member else None
|
||||
|
||||
def move_item(self, item, shelf_type, visibility=0, metadata=None):
|
||||
# shelf_type=None means remove from current shelf
|
||||
# metadata=None means no change
|
||||
if not item:
|
||||
raise ValueError("empty item")
|
||||
new_shelfmember = None
|
||||
last_shelfmember = self._shelf_member_for_item(item)
|
||||
last_shelfmember = self.locate_item(item)
|
||||
last_shelf = last_shelfmember.parent if last_shelfmember else None
|
||||
last_metadata = last_shelfmember.metadata if last_shelfmember else None
|
||||
last_visibility = last_shelfmember.visibility if last_shelfmember else None
|
||||
shelf = self.get_shelf(item.category, shelf_type) if shelf_type else None
|
||||
shelf = self.shelf_list[shelf_type] if shelf_type else None
|
||||
changed = False
|
||||
if last_shelf != shelf: # change shelf
|
||||
changed = True
|
||||
|
@ -596,20 +563,29 @@ class ShelfManager:
|
|||
"timestamp"
|
||||
)
|
||||
|
||||
def get_shelf(self, item_category, shelf_type):
|
||||
return (
|
||||
self.owner.shelf_set.all()
|
||||
.filter(item_category=item_category, shelf_type=shelf_type)
|
||||
.first()
|
||||
)
|
||||
def get_shelf(self, shelf_type):
|
||||
return self.shelf_list[shelf_type]
|
||||
|
||||
def get_items_on_shelf(self, item_category, shelf_type):
|
||||
shelf = (
|
||||
self.owner.shelf_set.all()
|
||||
.filter(item_category=item_category, shelf_type=shelf_type)
|
||||
.first()
|
||||
def get_members(self, shelf_type, item_category):
|
||||
return self.shelf_list[shelf_type].get_members_in_category(item_category)
|
||||
|
||||
# def get_items_on_shelf(self, item_category, shelf_type):
|
||||
# shelf = (
|
||||
# self.owner.shelf_set.all()
|
||||
# .filter(item_category=item_category, shelf_type=shelf_type)
|
||||
# .first()
|
||||
# )
|
||||
# return shelf.members.all().order_by
|
||||
|
||||
def get_title(self, shelf_type, item_category):
|
||||
ic = ItemCategory(item_category).label
|
||||
sts = [
|
||||
n[2] for n in ShelfTypeNames if n[0] == item_category and n[1] == shelf_type
|
||||
]
|
||||
st = sts[0] if sts else shelf_type
|
||||
return _("{shelf_label}的{item_category}").format(
|
||||
shelf_label=st, item_category=ic
|
||||
)
|
||||
return shelf.members.all().order_by
|
||||
|
||||
@staticmethod
|
||||
def get_manager_for_user(user):
|
||||
|
@ -820,7 +796,11 @@ class Mark:
|
|||
|
||||
@property
|
||||
def shelf_label(self):
|
||||
return self.shelfmember.parent.shelf_label if self.shelfmember else None
|
||||
return (
|
||||
self.owner.shelf_manager.get_title(self.shelf_type, self.item.category)
|
||||
if self.shelfmember
|
||||
else None
|
||||
)
|
||||
|
||||
@property
|
||||
def created_time(self):
|
||||
|
|
|
@ -35,12 +35,11 @@ class ShelfTest(TestCase):
|
|||
def test_shelf(self):
|
||||
user = User.objects.create(mastodon_site="site", username="name")
|
||||
shelf_manager = ShelfManager(user=user)
|
||||
shelf_manager.initialize()
|
||||
self.assertEqual(user.shelf_set.all().count(), 33)
|
||||
self.assertEqual(user.shelf_set.all().count(), 3)
|
||||
book1 = Edition.objects.create(title="Hyperion")
|
||||
book2 = Edition.objects.create(title="Andymion")
|
||||
q1 = shelf_manager.get_shelf(ItemCategory.Book, ShelfType.WISHLIST)
|
||||
q2 = shelf_manager.get_shelf(ItemCategory.Book, ShelfType.PROGRESS)
|
||||
q1 = shelf_manager.get_shelf(ShelfType.WISHLIST)
|
||||
q2 = shelf_manager.get_shelf(ShelfType.PROGRESS)
|
||||
self.assertIsNotNone(q1)
|
||||
self.assertIsNotNone(q2)
|
||||
self.assertEqual(q1.members.all().count(), 0)
|
||||
|
@ -123,7 +122,6 @@ class MarkTest(TestCase):
|
|||
def setUp(self):
|
||||
self.book1 = Edition.objects.create(title="Hyperion")
|
||||
self.user1 = User.objects.create(mastodon_site="site", username="name")
|
||||
self.user1.shelf_manager.initialize()
|
||||
pass
|
||||
|
||||
def test_mark(self):
|
||||
|
@ -139,7 +137,7 @@ class MarkTest(TestCase):
|
|||
|
||||
mark = Mark(self.user1, self.book1)
|
||||
self.assertEqual(mark.shelf_type, ShelfType.WISHLIST)
|
||||
self.assertEqual(mark.shelf_label, "想读")
|
||||
self.assertEqual(mark.shelf_label, "想读的书")
|
||||
self.assertEqual(mark.text, "a gentle comment")
|
||||
self.assertEqual(mark.rating, 9)
|
||||
self.assertEqual(mark.visibility, 1)
|
||||
|
|
|
@ -380,8 +380,7 @@ def _render_list(
|
|||
):
|
||||
return render_user_blocked(request)
|
||||
if type == "mark":
|
||||
shelf = user.shelf_manager.get_shelf(item_category, shelf_type)
|
||||
queryset = ShelfMember.objects.filter(owner=user, parent=shelf)
|
||||
queryset = user.shelf_manager.get_members(shelf_type, item_category)
|
||||
elif type == "tagmember":
|
||||
tag = Tag.objects.filter(owner=user, title=tag_title).first()
|
||||
if not tag:
|
||||
|
@ -555,10 +554,9 @@ def home(request, user_name):
|
|||
for category in visbile_categories:
|
||||
shelf_list[category] = {}
|
||||
for shelf_type in ShelfType:
|
||||
shelf = user.shelf_manager.get_shelf(category, shelf_type)
|
||||
members = shelf.recent_members.filter(qv)
|
||||
members = user.shelf_manager.get_members(shelf_type, category).filter(qv)
|
||||
shelf_list[category][shelf_type] = {
|
||||
"title": shelf.title,
|
||||
"title": user.shelf_manager.get_title(shelf_type, category),
|
||||
"count": members.count(),
|
||||
"members": members[:5].prefetch_related("item"),
|
||||
}
|
||||
|
|
|
@ -16,115 +16,133 @@ from django.db.models import Q, Count, Sum
|
|||
from django.utils import dateparse, timezone
|
||||
import re
|
||||
from legacy.models import *
|
||||
|
||||
from django.db import DatabaseError, transaction
|
||||
from music.models import SongMark
|
||||
from collection.models import CollectionItem
|
||||
|
||||
BATCH_SIZE = 1000
|
||||
|
||||
|
||||
def _book_convert(entity):
|
||||
content = ResourceContent(metadata={
|
||||
'title': entity.title,
|
||||
'brief': entity.brief,
|
||||
'cover_image_path': str(entity.cover),
|
||||
|
||||
'subtitle': entity.subtitle,
|
||||
'orig_title': entity.orig_title,
|
||||
'author': entity.author,
|
||||
'translator': entity.translator,
|
||||
'language': entity.language,
|
||||
'pub_house': entity.pub_house,
|
||||
'pub_year': entity.pub_year,
|
||||
'pub_month': entity.pub_month,
|
||||
'binding': entity.binding,
|
||||
'price': entity.price,
|
||||
'pages': entity.pages,
|
||||
'contents': entity.contents,
|
||||
'series': entity.other_info.get('丛书') if entity.other_info else None,
|
||||
'imprint': entity.other_info.get('出品方') if entity.other_info else None,
|
||||
})
|
||||
content = ResourceContent(
|
||||
metadata={
|
||||
"title": entity.title,
|
||||
"brief": entity.brief,
|
||||
"cover_image_path": str(entity.cover),
|
||||
"subtitle": entity.subtitle,
|
||||
"orig_title": entity.orig_title,
|
||||
"author": entity.author,
|
||||
"translator": entity.translator,
|
||||
"language": entity.language,
|
||||
"pub_house": entity.pub_house,
|
||||
"pub_year": entity.pub_year,
|
||||
"pub_month": entity.pub_month,
|
||||
"binding": entity.binding,
|
||||
"price": entity.price,
|
||||
"pages": entity.pages,
|
||||
"contents": entity.contents,
|
||||
"series": entity.other_info.get("丛书") if entity.other_info else None,
|
||||
"imprint": entity.other_info.get("出品方") if entity.other_info else None,
|
||||
}
|
||||
)
|
||||
if entity.isbn:
|
||||
t, v = detect_isbn_asin(entity.isbn)
|
||||
if t:
|
||||
content.lookup_ids[t] = v
|
||||
if entity.other_info and entity.other_info.get('统一书号'):
|
||||
content.lookup_ids[IdType.CUBN] = entity.other_info.get('统一书号')
|
||||
if entity.other_info and entity.other_info.get("统一书号"):
|
||||
content.lookup_ids[IdType.CUBN] = entity.other_info.get("统一书号")
|
||||
return content
|
||||
|
||||
|
||||
def _album_convert(entity):
|
||||
content = ResourceContent(metadata={
|
||||
'title': entity.title,
|
||||
'brief': entity.brief,
|
||||
'cover_image_path': str(entity.cover),
|
||||
|
||||
'other_title': entity.other_info.get('又名') if entity.other_info else None,
|
||||
'album_type': entity.other_info.get('专辑类型') if entity.other_info else None,
|
||||
'media': entity.other_info.get('介质') if entity.other_info else None,
|
||||
'disc_count': entity.other_info.get('碟片数') if entity.other_info else None,
|
||||
'artist': entity.artist,
|
||||
'genre': entity.genre,
|
||||
'release_date': entity.release_date.strftime('%Y-%m-%d') if entity.release_date else None,
|
||||
'duration': entity.duration,
|
||||
'company': entity.company,
|
||||
'track_list': entity.track_list,
|
||||
'bandcamp_album_id': entity.other_info.get('bandcamp_album_id') if entity.other_info else None,
|
||||
})
|
||||
if entity.other_info and entity.other_info.get('ISRC'):
|
||||
content.lookup_ids[IdType.ISRC] = entity.other_info.get('ISRC')
|
||||
if entity.other_info and entity.other_info.get('条形码'):
|
||||
content.lookup_ids[IdType.GTIN] = entity.other_info.get('条形码')
|
||||
if entity.other_info and entity.other_info.get('UPC'):
|
||||
content.lookup_ids[IdType.GTIN] = entity.other_info.get('UPC')
|
||||
content = ResourceContent(
|
||||
metadata={
|
||||
"title": entity.title,
|
||||
"brief": entity.brief,
|
||||
"cover_image_path": str(entity.cover),
|
||||
"other_title": entity.other_info.get("又名") if entity.other_info else None,
|
||||
"album_type": entity.other_info.get("专辑类型") if entity.other_info else None,
|
||||
"media": entity.other_info.get("介质") if entity.other_info else None,
|
||||
"disc_count": entity.other_info.get("碟片数") if entity.other_info else None,
|
||||
"artist": entity.artist,
|
||||
"genre": entity.genre,
|
||||
"release_date": entity.release_date.strftime("%Y-%m-%d")
|
||||
if entity.release_date
|
||||
else None,
|
||||
"duration": entity.duration,
|
||||
"company": entity.company,
|
||||
"track_list": entity.track_list,
|
||||
"bandcamp_album_id": entity.other_info.get("bandcamp_album_id")
|
||||
if entity.other_info
|
||||
else None,
|
||||
}
|
||||
)
|
||||
if entity.other_info and entity.other_info.get("ISRC"):
|
||||
content.lookup_ids[IdType.ISRC] = entity.other_info.get("ISRC")
|
||||
if entity.other_info and entity.other_info.get("条形码"):
|
||||
content.lookup_ids[IdType.GTIN] = entity.other_info.get("条形码")
|
||||
if entity.other_info and entity.other_info.get("UPC"):
|
||||
content.lookup_ids[IdType.GTIN] = entity.other_info.get("UPC")
|
||||
return content
|
||||
|
||||
|
||||
def _game_convert(entity):
|
||||
content = ResourceContent(metadata={
|
||||
'title': entity.title,
|
||||
'brief': entity.brief,
|
||||
'cover_image_path': str(entity.cover),
|
||||
|
||||
'other_title': entity.other_title,
|
||||
'developer': entity.developer,
|
||||
'publisher': entity.publisher,
|
||||
'release_date': entity.release_date.strftime('%Y-%m-%d') if entity.release_date else None,
|
||||
'genre': entity.genre,
|
||||
'platform': entity.platform,
|
||||
'official_site': entity.other_info.get('official_site') if entity.other_info else None,
|
||||
})
|
||||
if entity.other_info and entity.other_info.get('steam_url'):
|
||||
content.lookup_ids[IdType.Steam] = re.search(r'store\.steampowered\.com/app/(\d+)', entity.other_info.get('steam_url'))[1]
|
||||
content = ResourceContent(
|
||||
metadata={
|
||||
"title": entity.title,
|
||||
"brief": entity.brief,
|
||||
"cover_image_path": str(entity.cover),
|
||||
"other_title": entity.other_title,
|
||||
"developer": entity.developer,
|
||||
"publisher": entity.publisher,
|
||||
"release_date": entity.release_date.strftime("%Y-%m-%d")
|
||||
if entity.release_date
|
||||
else None,
|
||||
"genre": entity.genre,
|
||||
"platform": entity.platform,
|
||||
"official_site": entity.other_info.get("official_site")
|
||||
if entity.other_info
|
||||
else None,
|
||||
}
|
||||
)
|
||||
if entity.other_info and entity.other_info.get("steam_url"):
|
||||
content.lookup_ids[IdType.Steam] = re.search(
|
||||
r"store\.steampowered\.com/app/(\d+)", entity.other_info.get("steam_url")
|
||||
)[1]
|
||||
return content
|
||||
|
||||
|
||||
def _movie_tv_convert(entity):
|
||||
content = ResourceContent(metadata={
|
||||
'title': entity.title,
|
||||
'brief': entity.brief,
|
||||
'cover_image_path': str(entity.cover),
|
||||
|
||||
'orig_title': entity.orig_title,
|
||||
'other_title': entity.other_title,
|
||||
'director': entity.director,
|
||||
'playwright': entity.playwright,
|
||||
'actor': entity.actor,
|
||||
'genre': entity.genre,
|
||||
'showtime': entity.showtime,
|
||||
'site': entity.site,
|
||||
'area': entity.area,
|
||||
'language': entity.language,
|
||||
'year': entity.year,
|
||||
'duration': entity.duration,
|
||||
'season_count': entity.other_info.get('Seasons') if entity.other_info else None,
|
||||
'season_number': entity.season,
|
||||
'episode_count': entity.episodes,
|
||||
'single_episode_length': entity.single_episode_length,
|
||||
'is_series': entity.is_series,
|
||||
})
|
||||
content = ResourceContent(
|
||||
metadata={
|
||||
"title": entity.title,
|
||||
"brief": entity.brief,
|
||||
"cover_image_path": str(entity.cover),
|
||||
"orig_title": entity.orig_title,
|
||||
"other_title": entity.other_title,
|
||||
"director": entity.director,
|
||||
"playwright": entity.playwright,
|
||||
"actor": entity.actor,
|
||||
"genre": entity.genre,
|
||||
"showtime": entity.showtime,
|
||||
"site": entity.site,
|
||||
"area": entity.area,
|
||||
"language": entity.language,
|
||||
"year": entity.year,
|
||||
"duration": entity.duration,
|
||||
"season_count": entity.other_info.get("Seasons")
|
||||
if entity.other_info
|
||||
else None,
|
||||
"season_number": entity.season,
|
||||
"episode_count": entity.episodes,
|
||||
"single_episode_length": entity.single_episode_length,
|
||||
"is_series": entity.is_series,
|
||||
}
|
||||
)
|
||||
if entity.imdb_code:
|
||||
content.lookup_ids[IdType.IMDB] = entity.imdb_code
|
||||
if entity.other_info and entity.other_info.get('TMDB_ID'):
|
||||
content.lookup_ids[IdType.TMDB_TV] = entity.other_info.get('TMDB_ID')
|
||||
if entity.other_info and entity.other_info.get("TMDB_ID"):
|
||||
content.lookup_ids[IdType.TMDB_TV] = entity.other_info.get("TMDB_ID")
|
||||
return content
|
||||
|
||||
|
||||
|
@ -147,33 +165,77 @@ model_link = {
|
|||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Migrate legacy catalog'
|
||||
help = "Migrate legacy catalog"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--book', dest='types', action='append_const', const=Legacy_Book)
|
||||
parser.add_argument('--movie', dest='types', action='append_const', const=Legacy_Movie)
|
||||
parser.add_argument('--album', dest='types', action='append_const', const=Legacy_Album)
|
||||
parser.add_argument('--game', dest='types', action='append_const', const=Legacy_Game)
|
||||
parser.add_argument('--id', help='id to convert; or, if using with --max-id, the min id')
|
||||
parser.add_argument('--maxid', help='max id to convert')
|
||||
parser.add_argument('--failstop', help='stop on fail', action='store_true')
|
||||
parser.add_argument('--clearlink', help='clear legacy link table', action='store_true')
|
||||
parser.add_argument('--reload', help='reload and ignore existing ExternalResource', action='store_true')
|
||||
parser.add_argument(
|
||||
"--book", dest="types", action="append_const", const=Legacy_Book
|
||||
)
|
||||
parser.add_argument(
|
||||
"--movie", dest="types", action="append_const", const=Legacy_Movie
|
||||
)
|
||||
parser.add_argument(
|
||||
"--album", dest="types", action="append_const", const=Legacy_Album
|
||||
)
|
||||
parser.add_argument(
|
||||
"--game", dest="types", action="append_const", const=Legacy_Game
|
||||
)
|
||||
parser.add_argument("--song", help="process songs", action="store_true")
|
||||
parser.add_argument(
|
||||
"--id", help="id to convert; or, if using with --max-id, the min id"
|
||||
)
|
||||
parser.add_argument("--maxid", help="max id to convert")
|
||||
parser.add_argument("--failstop", help="stop on fail", action="store_true")
|
||||
parser.add_argument(
|
||||
"--clearlink", help="clear legacy link table", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reload",
|
||||
help="reload and ignore existing ExternalResource",
|
||||
action="store_true",
|
||||
)
|
||||
|
||||
def process_song(self, entity):
|
||||
if entity.album:
|
||||
new_uid = AlbumLink.objects.get(old_id=entity.album.id).new_uid
|
||||
else:
|
||||
new_uid = Album.objects.create(
|
||||
title=entity.title,
|
||||
brief=entity.brief,
|
||||
cover=entity.cover,
|
||||
artist=entity.artist,
|
||||
).uid
|
||||
if SongLink.objects.filter(old_id=entity.id).count() == 0:
|
||||
SongLink.objects.create(old_id=entity.id, new_uid=new_uid)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
types = options['types'] or [Legacy_Game, Legacy_Album, Legacy_Movie, Legacy_Book]
|
||||
reload = options['reload']
|
||||
if options["song"]:
|
||||
for sm in SongMark.objects.all():
|
||||
self.process_song(sm.song)
|
||||
for ci in CollectionItem.objects.filter(song__isnull=False):
|
||||
self.process_song(ci.song)
|
||||
return
|
||||
|
||||
types = options["types"] or [
|
||||
Legacy_Game,
|
||||
Legacy_Album,
|
||||
Legacy_Movie,
|
||||
Legacy_Book,
|
||||
]
|
||||
reload = options["reload"]
|
||||
for typ in types:
|
||||
print(typ)
|
||||
LinkModel = model_link[typ]
|
||||
if options['clearlink']:
|
||||
if options["clearlink"]:
|
||||
LinkModel.objects.all().delete()
|
||||
qs = typ.objects.all().order_by('id')
|
||||
if options['id']:
|
||||
if options['maxid']:
|
||||
qs = qs.filter(id__gte=int(options['id']), id__lte=int(options['maxid']))
|
||||
qs = typ.objects.all().order_by("id")
|
||||
if options["id"]:
|
||||
if options["maxid"]:
|
||||
qs = qs.filter(
|
||||
id__gte=int(options["id"]), id__lte=int(options["maxid"])
|
||||
)
|
||||
else:
|
||||
qs = qs.filter(id=int(options['id']))
|
||||
qs = qs.filter(id=int(options["id"]))
|
||||
|
||||
pg = Paginator(qs, BATCH_SIZE)
|
||||
for p in tqdm(pg.page_range):
|
||||
|
@ -185,34 +247,47 @@ class Command(BaseCommand):
|
|||
site = SiteManager.get_site_by_url(entity.source_url)
|
||||
item = None
|
||||
if site:
|
||||
if not site.DEFAULT_MODEL and not content.metadata.get('preferred_model'):
|
||||
if not site.DEFAULT_MODEL and not content.metadata.get(
|
||||
"preferred_model"
|
||||
):
|
||||
if model_map[typ] == Movie and entity.is_series:
|
||||
content.metadata['preferred_model'] = 'TVSeason' if entity.season else 'TVShow'
|
||||
content.metadata["preferred_model"] = (
|
||||
"TVSeason" if entity.season else "TVShow"
|
||||
)
|
||||
else:
|
||||
content.metadata['preferred_model'] = model_map[typ].__name__
|
||||
item = site.get_resource_ready(preloaded_content=content, ignore_existing_content=reload).item
|
||||
content.metadata["preferred_model"] = model_map[
|
||||
typ
|
||||
].__name__
|
||||
item = site.get_resource_ready(
|
||||
preloaded_content=content,
|
||||
ignore_existing_content=reload,
|
||||
).item
|
||||
else:
|
||||
# not known site, try save item without external resource
|
||||
item = None
|
||||
model = Edition
|
||||
model = model_map[typ]
|
||||
t, v = None, None
|
||||
if content.lookup_ids:
|
||||
t, v = Item.get_best_lookup_id(content.lookup_ids)
|
||||
item = model.objects.filter(primary_lookup_id_type=t, primary_lookup_id_value=v).first()
|
||||
item = model.objects.filter(
|
||||
primary_lookup_id_type=t,
|
||||
primary_lookup_id_value=v,
|
||||
).first()
|
||||
if not item:
|
||||
obj = model.copy_metadata(content.metadata)
|
||||
obj['primary_lookup_id_type'] = t
|
||||
obj['primary_lookup_id_value'] = v
|
||||
obj["primary_lookup_id_type"] = t
|
||||
obj["primary_lookup_id_value"] = v
|
||||
item = model.objects.create(**obj)
|
||||
item.cover = content.metadata['cover_image_path']
|
||||
item.cover = content.metadata["cover_image_path"]
|
||||
item.last_editor = entity.last_editor
|
||||
item.save()
|
||||
links.append(LinkModel(old_id=entity.id, new_uid=item.uid))
|
||||
# pprint.pp(site.get_item())
|
||||
except Exception as e:
|
||||
print(f'Convert failed for {typ} {entity.id}: {e}')
|
||||
if options['failstop']:
|
||||
raise(e)
|
||||
print(f"Convert failed for {typ} {entity.id}: {e}")
|
||||
if options["failstop"]:
|
||||
raise (e)
|
||||
# return
|
||||
LinkModel.objects.bulk_create(links)
|
||||
self.stdout.write(self.style.SUCCESS(f'Done.'))
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(f"Done."))
|
||||
|
|
|
@ -6,7 +6,7 @@ from games.models import Game as Legacy_Game
|
|||
from common.models import MarkStatusEnum
|
||||
from books.models import BookMark, BookReview
|
||||
from movies.models import MovieMark, MovieReview
|
||||
from music.models import AlbumMark, AlbumReview
|
||||
from music.models import AlbumMark, AlbumReview, SongMark, SongReview
|
||||
from games.models import GameMark, GameReview
|
||||
from collection.models import Collection as Legacy_Collection
|
||||
from collection.models import CollectionMark as Legacy_CollectionMark
|
||||
|
@ -35,14 +35,17 @@ model_link = {
|
|||
MovieMark: MovieLink,
|
||||
AlbumMark: AlbumLink,
|
||||
GameMark: GameLink,
|
||||
SongMark: SongLink,
|
||||
BookReview: BookLink,
|
||||
MovieReview: MovieLink,
|
||||
AlbumReview: AlbumLink,
|
||||
GameReview: GameLink,
|
||||
SongReview: SongLink,
|
||||
Legacy_Book: BookLink,
|
||||
Legacy_Movie: MovieLink,
|
||||
Legacy_Album: AlbumLink,
|
||||
Legacy_Game: GameLink,
|
||||
Legacy_Song: SongLink,
|
||||
}
|
||||
|
||||
shelf_map = {
|
||||
|
@ -55,6 +58,7 @@ tag_map = {
|
|||
BookMark: "bookmark_tags",
|
||||
MovieMark: "moviemark_tags",
|
||||
AlbumMark: "albummark_tags",
|
||||
SongMark: "songmark_tags",
|
||||
GameMark: "gamemark_tags",
|
||||
}
|
||||
|
||||
|
@ -75,6 +79,9 @@ class Command(BaseCommand):
|
|||
parser.add_argument(
|
||||
"--game", dest="types", action="append_const", const=GameMark
|
||||
)
|
||||
parser.add_argument(
|
||||
"--song", dest="types", action="append_const", const=SongMark
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mark",
|
||||
help="migrate shelves/tags/ratings, then exit",
|
||||
|
@ -104,7 +111,7 @@ class Command(BaseCommand):
|
|||
print("Initialize shelves")
|
||||
with transaction.atomic():
|
||||
for user in tqdm(User.objects.filter(is_active=True)):
|
||||
user.shelf_manager.initialize()
|
||||
temp = user.shelf_manager
|
||||
|
||||
def clear(self, classes):
|
||||
print("Deleting migrated user pieces")
|
||||
|
@ -196,12 +203,11 @@ class Command(BaseCommand):
|
|||
raise (e)
|
||||
|
||||
def mark(self, options):
|
||||
types = options["types"] or [GameMark, AlbumMark, MovieMark, BookMark]
|
||||
types = options["types"] or [GameMark, SongMark, AlbumMark, MovieMark, BookMark]
|
||||
print("Preparing cache")
|
||||
tag_cache = {f"{t.owner_id}_{t.title}": t.id for t in Tag.objects.all()}
|
||||
shelf_cache = {
|
||||
f"{s.owner_id}_{s.item_category}_{shelf_map[s.shelf_type]}": s.id
|
||||
for s in Shelf.objects.all()
|
||||
f"{s.owner_id}_{shelf_map[s.shelf_type]}": s.id for s in Shelf.objects.all()
|
||||
}
|
||||
|
||||
for typ in types:
|
||||
|
@ -255,9 +261,7 @@ class Command(BaseCommand):
|
|||
text=entity.text,
|
||||
visibility=visibility,
|
||||
)
|
||||
shelf = shelf_cache[
|
||||
f"{user_id}_{item.category}_{entity.status}"
|
||||
]
|
||||
shelf = shelf_cache[f"{user_id}_{entity.status}"]
|
||||
ShelfMember.objects.create(
|
||||
parent_id=shelf,
|
||||
owner_id=user_id,
|
||||
|
@ -309,7 +313,7 @@ class Command(BaseCommand):
|
|||
elif options["mark"]:
|
||||
if options["clear"]:
|
||||
self.clear(
|
||||
[Comment, Rating, TagMember, Tag, ShelfLogEntry, ShelfMember]
|
||||
[Comment, Rating, TagMember, Tag, ShelfLogEntry, ShelfMember, Shelf]
|
||||
)
|
||||
else:
|
||||
self.mark(options)
|
||||
|
|
|
@ -16,6 +16,11 @@ class AlbumLink(models.Model):
|
|||
new_uid = models.UUIDField()
|
||||
|
||||
|
||||
class SongLink(models.Model):
|
||||
old_id = models.IntegerField(db_index=True)
|
||||
new_uid = models.UUIDField()
|
||||
|
||||
|
||||
class GameLink(models.Model):
|
||||
old_id = models.IntegerField(db_index=True)
|
||||
new_uid = models.UUIDField()
|
||||
|
|
|
@ -11,9 +11,7 @@ class SocialTest(TestCase):
|
|||
self.book2 = Edition.objects.create(title="Andymion")
|
||||
self.movie = Edition.objects.create(title="Fight Club")
|
||||
self.alice = User.objects.create(mastodon_site="MySpace", username="Alice")
|
||||
self.alice.shelf_manager.initialize()
|
||||
self.bob = User.objects.create(mastodon_site="KKCity", username="Bob")
|
||||
self.bob.shelf_manager.initialize()
|
||||
|
||||
def test_timeline(self):
|
||||
# alice see 0 activity in timeline in the beginning
|
||||
|
@ -40,8 +38,8 @@ class SocialTest(TestCase):
|
|||
self.assertEqual(len(timeline2), 0)
|
||||
|
||||
# bob follows alice, see 2 activities
|
||||
self.bob.mastodon_following = ['Alice@MySpace']
|
||||
self.alice.mastodon_follower = ['Bob@KKCity']
|
||||
self.bob.mastodon_following = ["Alice@MySpace"]
|
||||
self.alice.mastodon_follower = ["Bob@KKCity"]
|
||||
self.bob.following = self.bob.get_following_ids()
|
||||
timeline2 = self.bob.activity_manager.get_timeline()
|
||||
self.assertEqual(len(timeline2), 2)
|
||||
|
|
Loading…
Add table
Reference in a new issue