fix unicode site name; add isort; split journal and users models
This commit is contained in:
parent
4e7583d6f1
commit
22640a74ab
163 changed files with 2318 additions and 1918 deletions
|
@ -12,8 +12,13 @@ repos:
|
|||
language_version: python3.11
|
||||
repos:
|
||||
- repo: https://github.com/Riverside-Healthcare/djLint
|
||||
rev: v1.30.2
|
||||
rev: v1.32.1
|
||||
hooks:
|
||||
- id: djlint-reformat-django
|
||||
- id: djlint-django
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
- id: isort
|
||||
args: ["--profile=black"]
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import os
|
||||
|
||||
NEODB_VERSION = "0.8"
|
||||
|
||||
PROJECT_ROOT = os.path.abspath(os.path.dirname(__name__))
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
|
|
|
@ -13,13 +13,14 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from users.views import login
|
||||
from common.api import api
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
from django.views.generic import RedirectView
|
||||
|
||||
from common.api import api
|
||||
from users.views import login
|
||||
|
||||
urlpatterns = [
|
||||
path("api/", api.urls), # type: ignore
|
||||
path("login/", login),
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
from django.http import Http404, HttpResponse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.http import HttpResponse
|
||||
from django.http import Http404
|
||||
from ninja import Schema
|
||||
|
||||
from common.api import *
|
||||
from .models import *
|
||||
|
||||
from .common import *
|
||||
from .models import *
|
||||
from .search.models import enqueue_fetch, get_fetch_lock, query_index
|
||||
from .sites import *
|
||||
from .search.models import enqueue_fetch, query_index, get_fetch_lock
|
||||
|
||||
|
||||
class SearchResult(Schema):
|
||||
|
|
|
@ -7,11 +7,9 @@ class CatalogConfig(AppConfig):
|
|||
|
||||
def ready(self):
|
||||
# load key modules in proper order, make sure class inject and signal works as expected
|
||||
from catalog import models
|
||||
from catalog import sites
|
||||
from catalog import api, models, sites
|
||||
from catalog.models import init_catalog_audit_log, init_catalog_search_models
|
||||
from journal import models as journal_models
|
||||
from catalog.models import init_catalog_search_models, init_catalog_audit_log
|
||||
from catalog import api
|
||||
|
||||
init_catalog_search_models()
|
||||
init_catalog_audit_log()
|
||||
|
|
|
@ -20,7 +20,9 @@ work data seems asymmetric (a book links to a work, but may not listed in that w
|
|||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
from .utils import *
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.book.models import *
|
||||
from catalog.book.utils import *
|
||||
from catalog.common import *
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import re
|
||||
|
||||
from .models import IdType
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from .models import *
|
||||
from .sites import *
|
||||
from .downloaders import *
|
||||
from .scrapers import *
|
||||
from . import jsondata
|
||||
|
||||
from .downloaders import *
|
||||
from .models import *
|
||||
from .scrapers import *
|
||||
from .sites import *
|
||||
|
||||
__all__ = (
|
||||
"IdType",
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import requests
|
||||
import filetype
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
from requests.exceptions import RequestException
|
||||
from django.conf import settings
|
||||
from pathlib import Path
|
||||
import json
|
||||
from io import StringIO
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
import logging
|
||||
from lxml import html
|
||||
from io import BytesIO, StringIO
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
|
||||
import filetype
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from lxml import html
|
||||
from PIL import Image
|
||||
from requests.exceptions import RequestException
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
import copy
|
||||
from datetime import date, datetime
|
||||
from importlib import import_module
|
||||
from functools import partialmethod
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from importlib import import_module
|
||||
|
||||
import django
|
||||
from django.core.exceptions import FieldError
|
||||
from django.db.models import fields
|
||||
from django.utils import dateparse, timezone
|
||||
|
||||
# from django.contrib.postgres.fields import ArrayField as DJANGO_ArrayField
|
||||
from django_jsonform.models.fields import ArrayField as DJANGO_ArrayField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# from django.db.models import JSONField as DJANGO_JSONField
|
||||
# from jsoneditor.fields.django3_jsonfield import JSONField as DJANGO_JSONField
|
||||
# from django.contrib.postgres.fields import ArrayField as DJANGO_ArrayField
|
||||
from django_jsonform.models.fields import ArrayField as DJANGO_ArrayField
|
||||
from django_jsonform.models.fields import JSONField as DJANGO_JSONField
|
||||
|
||||
|
||||
__all__ = (
|
||||
"BooleanField",
|
||||
"CharField",
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
from functools import cached_property
|
||||
from polymorphic.models import PolymorphicModel
|
||||
from django.db import models
|
||||
import logging
|
||||
import re
|
||||
from catalog.common import jsondata
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils import timezone
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.baseconv import base62
|
||||
import uuid
|
||||
from functools import cached_property
|
||||
from typing import cast
|
||||
from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
|
||||
from .mixins import SoftDeleteMixin
|
||||
from django.conf import settings
|
||||
from users.models import User
|
||||
from django.db import connection
|
||||
from ninja import Schema
|
||||
|
||||
from auditlog.context import disable_auditlog
|
||||
from auditlog.models import LogEntry, AuditlogHistoryField
|
||||
from auditlog.models import AuditlogHistoryField, LogEntry
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.db import connection, models
|
||||
from django.utils import timezone
|
||||
from django.utils.baseconv import base62
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ninja import Schema
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
from catalog.common import jsondata
|
||||
from users.models import User
|
||||
|
||||
from .mixins import SoftDeleteMixin
|
||||
from .utils import DEFAULT_ITEM_COVER, item_cover_path, resource_cover_path
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SiteName(models.TextChoices):
|
||||
Unknown = "unknown", _("未知站点")
|
||||
Douban = "douban", _("豆瓣")
|
||||
Goodreads = "goodreads", _("Goodreads")
|
||||
GoogleBooks = "googlebooks", _("谷歌图书")
|
||||
|
@ -482,6 +485,35 @@ class Item(SoftDeleteMixin, PolymorphicModel):
|
|||
def editable(self):
|
||||
return not self.is_deleted and self.merged_to_item is None
|
||||
|
||||
@property
|
||||
def rating(self):
|
||||
from journal.models import Rating
|
||||
|
||||
return Rating.get_rating_for_item(self)
|
||||
|
||||
@property
|
||||
def rating_count(self):
|
||||
from journal.models import Rating
|
||||
|
||||
return Rating.get_rating_count_for_item(self)
|
||||
|
||||
@property
|
||||
def rating_dist(self):
|
||||
from journal.models import Rating
|
||||
|
||||
return Rating.get_rating_distribution_for_item(self)
|
||||
|
||||
@property
|
||||
def tags(self):
|
||||
from journal.models import TagManager
|
||||
|
||||
return TagManager.indexable_tags_for_item(self)
|
||||
|
||||
def journal_exists(self):
|
||||
from journal.models import journal_exists_for_item
|
||||
|
||||
return journal_exists_for_item(self)
|
||||
|
||||
|
||||
class ItemLookupId(models.Model):
|
||||
item = models.ForeignKey(
|
||||
|
@ -542,12 +574,17 @@ class ExternalResource(models.Model):
|
|||
self.save()
|
||||
|
||||
def get_site(self):
|
||||
"""place holder only, this will be injected from SiteManager"""
|
||||
pass
|
||||
from .sites import SiteManager
|
||||
|
||||
return SiteManager.get_site_cls_by_id_type(self.id_type)
|
||||
|
||||
@property
|
||||
def site_name(self):
|
||||
return getattr(self.get_site(), "SITE_NAME")
|
||||
try:
|
||||
return self.get_site().SITE_NAME
|
||||
except:
|
||||
_logger.warning(f"Unknown site for {self}")
|
||||
return SiteName.Unknown
|
||||
|
||||
def update_content(self, resource_content):
|
||||
self.other_lookup_ids = resource_content.lookup_ids
|
||||
|
|
|
@ -6,14 +6,15 @@ a Site should map to a unique set of url patterns.
|
|||
a Site may scrape a url and store result in ResourceContent
|
||||
ResourceContent persists as an ExternalResource which may link to an Item
|
||||
"""
|
||||
from typing import Callable
|
||||
import re
|
||||
from .models import ExternalResource, IdType, IdealIdTypes, Item
|
||||
from dataclasses import dataclass, field
|
||||
import logging
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Callable
|
||||
|
||||
import django_rq
|
||||
|
||||
from .models import ExternalResource, IdealIdTypes, IdType, Item
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -297,11 +298,6 @@ class SiteManager:
|
|||
return SiteManager.register.values()
|
||||
|
||||
|
||||
ExternalResource.get_site = lambda resource: SiteManager.get_site_cls_by_id_type(
|
||||
resource.id_type
|
||||
) # type: ignore
|
||||
|
||||
|
||||
def crawl_related_resources_task(resource_pk):
|
||||
resource = ExternalResource.objects.filter(pk=resource_pk).first()
|
||||
if not resource:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
from django.utils import timezone
|
||||
import uuid
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.models import *
|
||||
from common.forms import PreviewImageInput
|
||||
|
||||
|
||||
CatalogForms = {}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from datetime import date
|
||||
from catalog.common.models import *
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
|
||||
class GameInSchema(ItemInSchema):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import pprint
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from catalog.common import SiteManager
|
||||
from catalog.sites import *
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import pprint
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, F
|
||||
import pprint
|
||||
|
||||
from catalog.models import *
|
||||
from journal.models import update_journal_for_merged_item
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from catalog.common import *
|
||||
import re
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from loguru import logger
|
||||
|
||||
from catalog.common import *
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Crawl content"
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from django.core.cache import cache
|
||||
from catalog.models import *
|
||||
from journal.models import ShelfMember, query_item_category, ItemCategory, Comment
|
||||
from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db.models import Count, F
|
||||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
|
||||
from catalog.models import *
|
||||
from journal.models import Comment, ItemCategory, ShelfMember, query_item_category
|
||||
|
||||
MAX_ITEMS_PER_PERIOD = 12
|
||||
MIN_MARKS = 2
|
||||
MAX_DAYS_FOR_PERIOD = 96
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
from django.conf import settings
|
||||
from catalog.models import *
|
||||
import pprint
|
||||
from django.core.paginator import Paginator
|
||||
from tqdm import tqdm
|
||||
from time import sleep
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.paginator import Paginator
|
||||
from django.utils import timezone
|
||||
from tqdm import tqdm
|
||||
|
||||
from catalog.models import *
|
||||
|
||||
BATCH_SIZE = 1000
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import pprint
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.core.paginator import Paginator
|
||||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
from tqdm import tqdm
|
||||
|
||||
from catalog.common.models import IdType
|
||||
from catalog.models import *
|
||||
from catalog.sites import RSS
|
||||
import pprint
|
||||
from django.core.paginator import Paginator
|
||||
from tqdm import tqdm
|
||||
from time import sleep
|
||||
from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 01:32
|
||||
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
from django.db import migrations, models
|
||||
|
||||
import catalog.common.mixins
|
||||
import catalog.common.utils
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 01:32
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.16 on 2023-02-02 03:47
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.16 on 2023-02-03 21:58
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 02:31
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-06 22:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,37 +1,41 @@
|
|||
import logging
|
||||
|
||||
from auditlog.registry import auditlog
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from .book.models import Edition, EditionInSchema, EditionSchema, Series, Work
|
||||
from .collection.models import Collection as CatalogCollection
|
||||
from .common.models import (
|
||||
ExternalResource,
|
||||
Item,
|
||||
ItemCategory,
|
||||
ItemSchema,
|
||||
item_content_types,
|
||||
item_categories,
|
||||
item_content_types,
|
||||
)
|
||||
from .book.models import Edition, Work, Series, EditionSchema, EditionInSchema
|
||||
from .movie.models import Movie, MovieSchema, MovieInSchema
|
||||
from .tv.models import (
|
||||
TVShow,
|
||||
TVSeason,
|
||||
TVEpisode,
|
||||
TVShowSchema,
|
||||
TVShowInSchema,
|
||||
TVSeasonSchema,
|
||||
TVSeasonInSchema,
|
||||
TVEpisodeSchema,
|
||||
)
|
||||
from .music.models import Album, AlbumSchema, AlbumInSchema
|
||||
from .game.models import Game, GameSchema, GameInSchema
|
||||
from .podcast.models import Podcast, PodcastSchema, PodcastInSchema, PodcastEpisode
|
||||
from .game.models import Game, GameInSchema, GameSchema
|
||||
from .movie.models import Movie, MovieInSchema, MovieSchema
|
||||
from .music.models import Album, AlbumInSchema, AlbumSchema
|
||||
from .performance.models import (
|
||||
Performance,
|
||||
PerformanceProduction,
|
||||
PerformanceSchema,
|
||||
PerformanceProductionSchema,
|
||||
PerformanceSchema,
|
||||
)
|
||||
from .collection.models import Collection as CatalogCollection
|
||||
from .search.models import Indexer
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.conf import settings
|
||||
import logging
|
||||
from auditlog.registry import auditlog
|
||||
from .podcast.models import Podcast, PodcastEpisode, PodcastInSchema, PodcastSchema
|
||||
from .tv.models import (
|
||||
TVEpisode,
|
||||
TVEpisodeSchema,
|
||||
TVSeason,
|
||||
TVSeasonInSchema,
|
||||
TVSeasonSchema,
|
||||
TVShow,
|
||||
TVShowInSchema,
|
||||
TVShowSchema,
|
||||
)
|
||||
|
||||
from .search.models import Indexer # isort:skip
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from catalog.common.models import *
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
|
||||
class MovieInSchema(ItemInSchema):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.common import *
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from datetime import date
|
||||
from catalog.common.models import *
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
|
||||
class AlbumInSchema(ItemInSchema):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from catalog.music.utils import *
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from functools import cached_property
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ninja import Schema
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.common.models import ItemSchema
|
||||
from catalog.common.utils import DEFAULT_ITEM_COVER
|
||||
from ninja import Schema
|
||||
|
||||
|
||||
class CrewMemberSchema(Schema):
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from catalog.common.models import *
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
|
||||
class PodcastInSchema(ItemInSchema):
|
||||
genre: list[str]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.test import TestCase
|
||||
from catalog.podcast.models import *
|
||||
from catalog.common import *
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.podcast.models import *
|
||||
|
||||
# class ApplePodcastTestCase(TestCase):
|
||||
# def setUp(self):
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import logging
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from lxml import html
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from catalog.sites.spotify import get_spotify_token
|
||||
import requests
|
||||
from lxml import html
|
||||
import logging
|
||||
|
||||
SEARCH_PAGE_SIZE = 5 # not all apis support page size
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from catalog.common.sites import SiteManager
|
||||
from ..models import TVSeason, Item
|
||||
from django.conf import settings
|
||||
import django_rq
|
||||
from rq.job import Job
|
||||
from django.core.cache import cache
|
||||
import hashlib
|
||||
from .typesense import Indexer as TypeSenseIndexer
|
||||
import logging
|
||||
|
||||
import django_rq
|
||||
from auditlog.context import set_actor
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rq.job import Job
|
||||
|
||||
from catalog.common.sites import SiteManager
|
||||
|
||||
from ..models import Item, TVSeason
|
||||
from .typesense import Indexer as TypeSenseIndexer
|
||||
|
||||
# from .meilisearch import Indexer as MeiliSearchIndexer
|
||||
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
from datetime import timedelta
|
||||
import types
|
||||
import logging
|
||||
import typesense
|
||||
from typesense.exceptions import ObjectNotFound
|
||||
from typesense.collection import Collection
|
||||
from django.conf import settings
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
from catalog.models import Item
|
||||
import types
|
||||
from datetime import timedelta
|
||||
from pprint import pprint
|
||||
|
||||
import django_rq
|
||||
from rq.job import Job
|
||||
import typesense
|
||||
from django.conf import settings
|
||||
from django.db.models.signals import post_delete, post_save
|
||||
from django_redis import get_redis_connection
|
||||
from rq.job import Job
|
||||
from typesense.collection import Collection
|
||||
from typesense.exceptions import ObjectNotFound
|
||||
|
||||
from catalog.models import Item
|
||||
|
||||
INDEX_NAME = "catalog"
|
||||
SEARCHABLE_ATTRIBUTES = [
|
||||
|
|
|
@ -1,22 +1,21 @@
|
|||
from ..common.sites import SiteManager
|
||||
from .apple_music import AppleMusic
|
||||
from .bandcamp import Bandcamp
|
||||
from .bangumi import Bangumi
|
||||
from .bookstw import BooksTW
|
||||
from .discogs import DiscogsMaster, DiscogsRelease
|
||||
from .douban_book import DoubanBook
|
||||
from .douban_drama import DoubanDrama
|
||||
from .douban_game import DoubanGame
|
||||
from .douban_movie import DoubanMovie
|
||||
from .douban_music import DoubanMusic
|
||||
from .goodreads import Goodreads
|
||||
from .google_books import GoogleBooks
|
||||
from .igdb import IGDB
|
||||
from .imdb import IMDB
|
||||
|
||||
# from .apple_podcast import ApplePodcast
|
||||
from .rss import RSS
|
||||
from .douban_book import DoubanBook
|
||||
from .douban_movie import DoubanMovie
|
||||
from .douban_music import DoubanMusic
|
||||
from .douban_game import DoubanGame
|
||||
from .douban_drama import DoubanDrama
|
||||
from .goodreads import Goodreads
|
||||
from .google_books import GoogleBooks
|
||||
from .tmdb import TMDB_Movie
|
||||
from .imdb import IMDB
|
||||
from .spotify import Spotify
|
||||
from .igdb import IGDB
|
||||
from .steam import Steam
|
||||
from .bandcamp import Bandcamp
|
||||
from .bangumi import Bangumi
|
||||
from .discogs import DiscogsRelease
|
||||
from .discogs import DiscogsMaster
|
||||
from .bookstw import BooksTW
|
||||
from .apple_music import AppleMusic
|
||||
from .tmdb import TMDB_Movie
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import logging
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
import logging
|
||||
|
||||
from .rss import RSS
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import json
|
||||
import logging
|
||||
import re
|
||||
import urllib.parse
|
||||
|
||||
import dateparser
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
import logging
|
||||
import urllib.parse
|
||||
import dateparser
|
||||
import re
|
||||
import json
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
import logging
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from catalog.common import *
|
||||
from catalog.book.models import *
|
||||
from catalog.book.utils import *
|
||||
from .douban import *
|
||||
import logging
|
||||
|
||||
from catalog.book.models import *
|
||||
from catalog.book.utils import *
|
||||
from catalog.common import *
|
||||
|
||||
from .douban import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
"""
|
||||
Discogs.
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from catalog.music.utils import upc_to_gtin_13
|
||||
from .douban import *
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from .douban import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import re
|
||||
from catalog.common import *
|
||||
|
||||
from catalog.common import *
|
||||
|
||||
RE_NUMBERS = re.compile(r"\d+\d*")
|
||||
RE_WHITESPACES = re.compile(r"\s+")
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
from django.utils.timezone import make_aware
|
||||
from datetime import datetime
|
||||
from catalog.book.models import Edition, Work
|
||||
from catalog.common import *
|
||||
from catalog.book.utils import detect_isbn_asin
|
||||
from lxml import html
|
||||
import json
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from django.utils.timezone import make_aware
|
||||
from lxml import html
|
||||
|
||||
from catalog.book.models import Edition, Work
|
||||
from catalog.book.utils import detect_isbn_asin
|
||||
from catalog.common import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import logging
|
||||
import re
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
import re
|
||||
import logging
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -4,15 +4,16 @@ IGDB
|
|||
use (e.g. "portal-2") as id, which is different from real id in IGDB API
|
||||
"""
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from django.conf import settings
|
||||
from igdb.wrapper import IGDBWrapper
|
||||
import requests
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from igdb.wrapper import IGDBWrapper
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import json
|
||||
from catalog.common import *
|
||||
from .tmdb import search_tmdb_by_imdb_id
|
||||
from catalog.movie.models import *
|
||||
from catalog.tv.models import *
|
||||
import logging
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.movie.models import *
|
||||
from catalog.tv.models import *
|
||||
|
||||
from .tmdb import search_tmdb_by_imdb_id
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
import logging
|
||||
import podcastparser
|
||||
import pickle
|
||||
import urllib.request
|
||||
from django.core.cache import cache
|
||||
from catalog.podcast.models import PodcastEpisode
|
||||
from datetime import datetime
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
import bleach
|
||||
from django.core.validators import URLValidator
|
||||
import podcastparser
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import URLValidator
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.common.downloaders import (
|
||||
_local_response_path,
|
||||
get_mock_file,
|
||||
get_mock_mode,
|
||||
_local_response_path,
|
||||
)
|
||||
import pickle
|
||||
from catalog.models import *
|
||||
from catalog.podcast.models import PodcastEpisode
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
"""
|
||||
Spotify
|
||||
"""
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
|
||||
import dateparser
|
||||
import requests
|
||||
from django.conf import settings
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from catalog.music.utils import upc_to_gtin_13
|
||||
from .douban import *
|
||||
import time
|
||||
import datetime
|
||||
import requests
|
||||
import dateparser
|
||||
import logging
|
||||
|
||||
from .douban import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
from .igdb import search_igdb_by_3p_url
|
||||
import dateparser
|
||||
import logging
|
||||
|
||||
import dateparser
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.models import *
|
||||
|
||||
from .igdb import search_igdb_by_3p_url
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -2,14 +2,16 @@
|
|||
The Movie Database
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from catalog.common import *
|
||||
from .douban import *
|
||||
from catalog.movie.models import *
|
||||
from catalog.tv.models import *
|
||||
import logging
|
||||
|
||||
from .douban import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.book.tests import *
|
||||
from catalog.movie.tests import *
|
||||
from catalog.tv.tests import *
|
||||
from catalog.music.tests import *
|
||||
from catalog.game.tests import *
|
||||
from catalog.podcast.tests import *
|
||||
from catalog.movie.tests import *
|
||||
from catalog.music.tests import *
|
||||
from catalog.performance.tests import *
|
||||
from catalog.podcast.tests import *
|
||||
from catalog.tv.tests import *
|
||||
|
||||
# imported tests with same name might be ignored silently
|
||||
|
|
|
@ -25,10 +25,12 @@ For now, we follow Douban convention, but keep an eye on it in case it breaks it
|
|||
|
||||
"""
|
||||
from functools import cached_property
|
||||
from catalog.common.models import *
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.common.models import *
|
||||
|
||||
|
||||
class TVShowInSchema(ItemInSchema):
|
||||
season_count: int | None = None
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from django.test import TestCase
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.tv.models import *
|
||||
from catalog.sites.imdb import IMDB
|
||||
from catalog.tv.models import *
|
||||
|
||||
|
||||
class JSONFieldTestCase(TestCase):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.urls import path, re_path
|
||||
from .views import *
|
||||
|
||||
from .models import *
|
||||
from .views import *
|
||||
|
||||
app_name = "catalog"
|
||||
|
||||
|
|
|
@ -1,24 +1,32 @@
|
|||
import logging
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import BadRequest, PermissionDenied, ObjectDoesNotExist
|
||||
from django.db.models import Count
|
||||
from django.core.paginator import Paginator
|
||||
from .models import *
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from journal.models import Mark, ShelfMember, Review, Comment, query_item_category
|
||||
from journal.models import (
|
||||
query_visible,
|
||||
query_following,
|
||||
)
|
||||
from common.utils import PageLinksGenerator, get_uuid_or_404
|
||||
from common.config import PAGE_LINK_NUMBER
|
||||
from journal.models import ShelfTypeNames, ShelfType, ItemCategory
|
||||
from .forms import *
|
||||
from .search.views import *
|
||||
from django.http import Http404
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Count
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
|
||||
from common.config import PAGE_LINK_NUMBER
|
||||
from common.utils import PageLinksGenerator, get_uuid_or_404
|
||||
from journal.models import (
|
||||
Comment,
|
||||
Mark,
|
||||
Review,
|
||||
ShelfMember,
|
||||
ShelfType,
|
||||
ShelfTypeNames,
|
||||
query_following,
|
||||
query_item_category,
|
||||
query_visible,
|
||||
)
|
||||
|
||||
from .forms import *
|
||||
from .models import *
|
||||
from .search.views import *
|
||||
from .views_edit import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
@ -205,7 +213,8 @@ def comments_by_episode(request, item_path, item_uuid):
|
|||
raise Http404()
|
||||
episode_uuid = request.GET.get("episode_uuid")
|
||||
if episode_uuid:
|
||||
ids = [TVEpisode.get_by_url(episode_uuid).id]
|
||||
episode = TVEpisode.get_by_url(episode_uuid)
|
||||
ids = [episode.pk] if episode else []
|
||||
else:
|
||||
ids = item.child_item_ids
|
||||
queryset = Comment.objects.filter(item_id__in=ids).order_by("-created_time")
|
||||
|
@ -250,7 +259,7 @@ def discover(request):
|
|||
raise BadRequest()
|
||||
user = request.user
|
||||
if user.is_authenticated:
|
||||
layout = user.get_preference().discover_layout
|
||||
layout = user.preference.discover_layout
|
||||
else:
|
||||
layout = []
|
||||
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
import logging
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.core.exceptions import BadRequest, PermissionDenied, ObjectDoesNotExist
|
||||
from django.utils import timezone
|
||||
from django.contrib import messages
|
||||
from .common.models import ExternalResource, IdType, IdealIdTypes
|
||||
from .sites.imdb import IMDB
|
||||
from .models import *
|
||||
from .forms import *
|
||||
from .search.views import *
|
||||
from journal.models import update_journal_for_merged_item
|
||||
from common.utils import get_uuid_or_404
|
||||
|
||||
from auditlog.context import set_actor
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.core.exceptions import BadRequest, ObjectDoesNotExist, PermissionDenied
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.utils import get_uuid_or_404
|
||||
from journal.models import update_journal_for_merged_item
|
||||
|
||||
from .common.models import ExternalResource, IdealIdTypes, IdType
|
||||
from .forms import *
|
||||
from .models import *
|
||||
from .search.views import *
|
||||
from .sites.imdb import IMDB
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
from ninja import NinjaAPI, Schema
|
||||
from django.conf import settings
|
||||
import logging
|
||||
from typing import Any, Callable, List, Optional, Tuple, Type
|
||||
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import QuerySet
|
||||
from ninja import NinjaAPI, Schema
|
||||
from ninja.pagination import PageNumberPagination as NinjaPageNumberPagination
|
||||
from ninja.security import HttpBearer
|
||||
from oauthlib.oauth2 import Server
|
||||
from oauth2_provider.oauth2_backends import OAuthLibCore
|
||||
from oauth2_provider.oauth2_validators import OAuth2Validator
|
||||
import logging
|
||||
from oauthlib.oauth2 import Server
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from django import forms
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
import django.contrib.postgres.forms as postgres
|
||||
from django.utils import formats
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import json
|
||||
|
||||
import django.contrib.postgres.forms as postgres
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import formats
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
|
||||
|
||||
class PreviewImageInput(forms.FileInput):
|
||||
template_name = "widgets/image.html"
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import pprint
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from redis import Redis
|
||||
from rq.job import Job
|
||||
from rq import Queue
|
||||
from rq.job import Job
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import pprint
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from redis import Redis
|
||||
from rq.job import Job
|
||||
from rq import Queue
|
||||
from rq.job import Job
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
|
@ -2,7 +2,6 @@ from django import template
|
|||
from django.conf import settings
|
||||
from django.utils.html import format_html
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.text import Truncator
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.text import Truncator
|
||||
|
||||
from catalog.common.models import ItemCategory, item_categories
|
||||
from catalog.search.views import visible_categories as _visible_categories
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from django import template
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from opencc import OpenCC
|
||||
import re
|
||||
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import mark_safe
|
||||
from opencc import OpenCC
|
||||
|
||||
cc = OpenCC("t2s")
|
||||
register = template.Library()
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ from django.conf import settings
|
|||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django import template
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ from django import template
|
|||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.text import Truncator
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.urls import path
|
||||
|
||||
from .views import *
|
||||
|
||||
app_name = "common"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import uuid
|
||||
|
||||
from django.http import Http404
|
||||
from django.utils import timezone
|
||||
from django.utils.baseconv import base62
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -11,7 +11,7 @@ def me(request):
|
|||
|
||||
def home(request):
|
||||
if request.user.is_authenticated:
|
||||
home = request.user.get_preference().classic_homepage
|
||||
home = request.user.preference.classic_homepage
|
||||
if home == 1:
|
||||
return redirect(request.user.url)
|
||||
elif home == 2:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-28 05:09
|
||||
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import markdownx.models
|
||||
import oauth2_provider.generators
|
||||
import oauth2_provider.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-06 22:53
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from django.db import models
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from oauth2_provider.models import AbstractApplication
|
||||
from markdownx.models import MarkdownxField
|
||||
from journal.renderers import render_md
|
||||
from oauth2_provider.models import AbstractApplication
|
||||
|
||||
from journal.models.renderers import render_md
|
||||
|
||||
|
||||
class Application(AbstractApplication):
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from django.urls import path, re_path, include
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import include, path, re_path
|
||||
from oauth2_provider import views as oauth2_views
|
||||
from oauth2_provider.views import oidc as oidc_views
|
||||
from .views import *
|
||||
|
||||
from .views import *
|
||||
|
||||
_urlpatterns = [
|
||||
re_path(
|
||||
|
|
|
@ -1,23 +1,22 @@
|
|||
from django.shortcuts import render
|
||||
from loguru import logger
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.forms.models import modelform_factory
|
||||
from django.shortcuts import render
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from loguru import logger
|
||||
from oauth2_provider.forms import AllowForm
|
||||
from oauth2_provider.models import get_application_model
|
||||
from oauth2_provider.generators import generate_client_id, generate_client_secret
|
||||
from oauth2_provider.models import AccessToken, RefreshToken, get_application_model
|
||||
from oauth2_provider.settings import oauth2_settings
|
||||
from oauth2_provider.views import ApplicationRegistration as BaseApplicationRegistration
|
||||
from oauth2_provider.views import ApplicationUpdate as BaseApplicationUpdate
|
||||
from oauth2_provider.views.base import AuthorizationView as BaseAuthorizationView
|
||||
from oauth2_provider.settings import oauth2_settings
|
||||
from oauth2_provider.generators import generate_client_id, generate_client_secret
|
||||
from common.api import api
|
||||
from oauthlib.common import generate_token
|
||||
from oauth2_provider.models import AccessToken
|
||||
from django.utils import timezone
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from oauth2_provider.models import RefreshToken
|
||||
from django.conf import settings
|
||||
from .models import Application
|
||||
from django.forms.models import modelform_factory
|
||||
|
||||
from common.api import api
|
||||
|
||||
from .models import Application
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
from .models import *
|
||||
from ninja import Schema
|
||||
from common.api import *
|
||||
from oauth2_provider.decorators import protected_resource
|
||||
from ninja.security import django_auth
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from catalog.common.models import *
|
||||
from typing import List
|
||||
from ninja.pagination import paginate
|
||||
from ninja import Field
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils import timezone
|
||||
from ninja import Field, Schema
|
||||
from ninja.pagination import paginate
|
||||
from ninja.security import django_auth
|
||||
from oauth2_provider.decorators import protected_resource
|
||||
|
||||
from catalog.common.models import *
|
||||
from common.api import *
|
||||
|
||||
from .models import *
|
||||
|
||||
|
||||
class MarkSchema(Schema):
|
||||
|
|
|
@ -7,9 +7,10 @@ class JournalConfig(AppConfig):
|
|||
|
||||
def ready(self):
|
||||
# load key modules in proper order, make sure class inject and signal works as expected
|
||||
from . import api
|
||||
from .models import Tag, Rating
|
||||
from catalog.models import Indexer
|
||||
|
||||
from . import api
|
||||
from .models import Rating, Tag
|
||||
|
||||
Indexer.register_list_model(Tag)
|
||||
Indexer.register_piece_model(Rating)
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from openpyxl import Workbook
|
||||
|
||||
from catalog.common.models import IdType
|
||||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
from datetime import datetime
|
||||
import os
|
||||
from journal.models import *
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
from django.contrib.syndication.views import Feed
|
||||
from journal.renderers import render_md
|
||||
import mimetypes
|
||||
from .models import *
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.syndication.views import Feed
|
||||
|
||||
from journal.models.renderers import render_md
|
||||
|
||||
from .models import *
|
||||
|
||||
MAX_ITEM_PER_TYPE = 10
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from django import forms
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .models import *
|
||||
from markdownx.fields import MarkdownxFormField
|
||||
|
||||
from common.forms import PreviewImageInput
|
||||
|
||||
from .models import *
|
||||
|
||||
|
||||
class ReviewForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
import openpyxl
|
||||
import re
|
||||
from markdownify import markdownify as md
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from user_messages import api as msg
|
||||
import django_rq
|
||||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
import django_rq
|
||||
import openpyxl
|
||||
import pytz
|
||||
from auditlog.context import set_actor
|
||||
from django.conf import settings
|
||||
from markdownify import markdownify as md
|
||||
from user_messages import api as msg
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.common.downloaders import *
|
||||
from catalog.models import *
|
||||
from catalog.sites.douban import DoubanDownloader
|
||||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
from journal.models import *
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import re
|
||||
from datetime import datetime
|
||||
from user_messages import api as msg
|
||||
|
||||
import django_rq
|
||||
from django.utils.timezone import make_aware
|
||||
from auditlog.context import set_actor
|
||||
from django.utils.timezone import make_aware
|
||||
from user_messages import api as msg
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.common.downloaders import *
|
||||
from catalog.models import *
|
||||
from journal.models import *
|
||||
from catalog.common.downloaders import *
|
||||
|
||||
|
||||
re_list = r"^https://www.goodreads.com/list/show/\d+"
|
||||
re_shelf = r"^https://www.goodreads.com/review/list/\d+[^?]*\?shelf=[^&]+"
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
from django.core.files import uploadedfile
|
||||
import listparser
|
||||
from catalog.sites.rss import RSS
|
||||
import openpyxl
|
||||
import re
|
||||
from markdownify import markdownify as md
|
||||
from datetime import datetime
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
import django_rq
|
||||
import listparser
|
||||
import openpyxl
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.core.files import uploadedfile
|
||||
from markdownify import markdownify as md
|
||||
from user_messages import api as msg
|
||||
import django_rq
|
||||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
import os
|
||||
|
||||
from catalog.common import *
|
||||
from catalog.common.downloaders import *
|
||||
from catalog.sites.rss import RSS
|
||||
from common.utils import GenerateDateUUIDMediaFilePath
|
||||
from journal.models import *
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
import pprint
|
||||
from journal.models import *
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from journal.importers.douban import DoubanImporter
|
||||
from journal.models import *
|
||||
from users.models import User
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 01:32
|
||||
|
||||
import catalog.common.utils
|
||||
import uuid
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import journal.mixins
|
||||
import markdownx.models
|
||||
import uuid
|
||||
from django.db import migrations, models
|
||||
|
||||
import catalog.common.utils
|
||||
import journal.models.mixins
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -39,7 +41,7 @@ class Migration(migrations.Migration):
|
|||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
bases=(models.Model, journal.mixins.UserOwnedObjectMixin),
|
||||
bases=(models.Model, journal.models.mixins.UserOwnedObjectMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Collection",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 01:32
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 21:06
|
||||
|
||||
import catalog.common.utils
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import catalog.common.utils
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-14 03:34
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-14 13:39
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-17 03:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-31 20:14
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 02:31
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Generated by Django 4.2.3 on 2023-07-06 22:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
|
1309
journal/models.py
1309
journal/models.py
File diff suppressed because it is too large
Load diff
31
journal/models/__init__.py
Normal file
31
journal/models/__init__.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from .collection import Collection, CollectionMember, FeaturedCollection
|
||||
from .comment import Comment
|
||||
from .common import (
|
||||
Piece,
|
||||
UserOwnedObjectMixin,
|
||||
VisibilityType,
|
||||
max_visiblity_to,
|
||||
q_visible_to,
|
||||
query_following,
|
||||
query_item_category,
|
||||
query_visible,
|
||||
)
|
||||
from .like import Like
|
||||
from .mark import Mark
|
||||
from .rating import Rating
|
||||
from .review import Review
|
||||
from .shelf import (
|
||||
Shelf,
|
||||
ShelfLogEntry,
|
||||
ShelfManager,
|
||||
ShelfMember,
|
||||
ShelfType,
|
||||
ShelfTypeNames,
|
||||
)
|
||||
from .tag import Tag, TagManager, TagMember
|
||||
from .utils import (
|
||||
journal_exists_for_item,
|
||||
remove_data_by_user,
|
||||
reset_journal_visibility_for_user,
|
||||
update_journal_for_merged_item,
|
||||
)
|
111
journal/models/collection.py
Normal file
111
journal/models/collection.py
Normal file
|
@ -0,0 +1,111 @@
|
|||
import re
|
||||
from functools import cached_property
|
||||
|
||||
from django.db import connection, models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from catalog.collection.models import Collection as CatalogCollection
|
||||
from catalog.common import jsondata
|
||||
from catalog.common.utils import DEFAULT_ITEM_COVER, piece_cover_path
|
||||
from catalog.models import Item
|
||||
from users.models import User
|
||||
|
||||
from .common import Piece
|
||||
from .itemlist import List, ListMember
|
||||
from .renderers import render_md
|
||||
|
||||
_RE_HTML_TAG = re.compile(r"<[^>]*>")
|
||||
|
||||
|
||||
class CollectionMember(ListMember):
|
||||
parent = models.ForeignKey(
|
||||
"Collection", related_name="members", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
note = jsondata.CharField(_("备注"), null=True, blank=True)
|
||||
|
||||
|
||||
class Collection(List):
|
||||
url_path = "collection"
|
||||
MEMBER_CLASS = CollectionMember
|
||||
catalog_item = models.OneToOneField(
|
||||
CatalogCollection, on_delete=models.PROTECT, related_name="journal_item"
|
||||
)
|
||||
title = models.CharField(_("标题"), max_length=1000, default="")
|
||||
brief = models.TextField(_("简介"), blank=True, default="")
|
||||
cover = models.ImageField(
|
||||
upload_to=piece_cover_path, default=DEFAULT_ITEM_COVER, blank=True
|
||||
)
|
||||
items = models.ManyToManyField(
|
||||
Item, through="CollectionMember", related_name="collections"
|
||||
)
|
||||
collaborative = models.PositiveSmallIntegerField(
|
||||
default=0
|
||||
) # 0: Editable by owner only / 1: Editable by bi-direction followers
|
||||
featured_by_users = models.ManyToManyField(
|
||||
to=User, related_name="featured_collections", through="FeaturedCollection"
|
||||
)
|
||||
|
||||
@property
|
||||
def html(self):
|
||||
html = render_md(self.brief)
|
||||
return html
|
||||
|
||||
@property
|
||||
def plain_description(self):
|
||||
html = render_md(self.brief)
|
||||
return _RE_HTML_TAG.sub(" ", html)
|
||||
|
||||
def featured_by_user_since(self, user):
|
||||
f = FeaturedCollection.objects.filter(target=self, owner=user).first()
|
||||
return f.created_time if f else None
|
||||
|
||||
def get_stats_for_user(self, user):
|
||||
items = list(self.members.all().values_list("item_id", flat=True))
|
||||
stats = {"total": len(items)}
|
||||
for st, shelf in user.shelf_manager.shelf_list.items():
|
||||
stats[st] = shelf.members.all().filter(item_id__in=items).count()
|
||||
stats["percentage"] = (
|
||||
round(stats["complete"] * 100 / stats["total"]) if stats["total"] else 0
|
||||
)
|
||||
return stats
|
||||
|
||||
def get_progress_for_user(self, user):
|
||||
items = list(self.members.all().values_list("item_id", flat=True))
|
||||
if len(items) == 0:
|
||||
return 0
|
||||
shelf = user.shelf_manager.shelf_list["complete"]
|
||||
return round(
|
||||
shelf.members.all().filter(item_id__in=items).count() * 100 / len(items)
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if getattr(self, "catalog_item", None) is None:
|
||||
self.catalog_item = CatalogCollection()
|
||||
if (
|
||||
self.catalog_item.title != self.title
|
||||
or self.catalog_item.brief != self.brief
|
||||
):
|
||||
self.catalog_item.title = self.title
|
||||
self.catalog_item.brief = self.brief
|
||||
self.catalog_item.cover = self.cover # type: ignore
|
||||
self.catalog_item.save()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class FeaturedCollection(Piece):
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
target = models.ForeignKey(Collection, on_delete=models.CASCADE)
|
||||
created_time = models.DateTimeField(auto_now_add=True)
|
||||
edited_time = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = [["owner", "target"]]
|
||||
|
||||
@property
|
||||
def visibility(self):
|
||||
return self.target.visibility
|
||||
|
||||
@cached_property
|
||||
def progress(self):
|
||||
return self.target.get_progress_for_user(self.owner)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue