blender-studio/training/queries/sections.py

90 lines
3.5 KiB
Python

# noqa: D100
import datetime
from typing import List, Optional, Tuple, cast
from django.db.models import Exists, OuterRef
from comments import models
from comments.queries import get_annotated_comments
from training.models import chapters, sections, trainings
import static_assets.models as models_static_assets
def recently_watched(*, user_pk: int) -> List[sections.Section]: # noqa: D103
return list(
sections.Section.objects.raw(
'''
SELECT *
FROM (SELECT s.*,
c.index AS chapter_index,
c.name AS chapter_name,
t.name AS training_name,
uvp.position AS video_position,
v.duration AS video_duration,
row_number()
OVER (
PARTITION BY t.id ORDER BY coalesce(uvp.date_updated, usp.date_updated)
DESC
) AS row_number_per_training
FROM training_usersectionprogress usp
LEFT JOIN training_section s ON usp.section_id = s.id
LEFT JOIN training_chapter c ON s.chapter_id = c.id
LEFT JOIN training_training t ON c.training_id = t.id
LEFT JOIN static_assets_staticasset sa ON s.static_asset_id = sa.id
LEFT JOIN static_assets_video v ON sa.id = v.static_asset_id
LEFT JOIN static_assets_uservideoprogress uvp
ON v.id = uvp.video_id AND usp.user_id = uvp.user_id
WHERE usp.user_id = %s
AND usp.started
AND NOT usp.finished
ORDER BY coalesce(uvp.date_updated, usp.date_updated) DESC) progress
WHERE progress.row_number_per_training = 1;
''',
[user_pk],
)
)
def from_slug( # noqa: D103
*, user_pk: int, training_slug: str, section_slug: str, **filters
) -> Optional[
Tuple[
trainings.Training,
bool,
chapters.Chapter,
sections.Section,
Optional[Tuple[models_static_assets.Video, Optional[datetime.timedelta]]],
List[models.Comment],
]
]:
try:
section = (
sections.Section.objects.filter(**filters)
.annotate(
training_favorited=Exists(
trainings.Favorite.objects.filter(
user_id=user_pk, training_id=OuterRef('chapter__training_id')
)
)
)
.select_related('chapter__training', 'chapter')
.prefetch_related('static_asset', 'comments', 'comments__user')
.get(chapter__training__slug=training_slug, slug=section_slug)
)
except sections.Section.DoesNotExist:
return None
video: Optional[Tuple[models_static_assets.Video, Optional[datetime.timedelta]]]
try:
_video = section.static_asset.video if section.static_asset else None
progress_position = _video.get_progress_position(user_pk) if _video else None
video = (_video, progress_position) if _video else None
except models_static_assets.Video.DoesNotExist:
video = None
chapter = section.chapter
training = chapter.training
training_favorited = cast(bool, getattr(section, 'training_favorited'))
comments = get_annotated_comments(section, user_pk)
return training, training_favorited, chapter, section, video, comments