lib.itmens/catalog/views.py
2024-06-03 08:00:19 -04:00

287 lines
9.4 KiB
Python

from django.contrib.auth.decorators import login_required
from django.core.cache import cache
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.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.http import require_http_methods
from common.utils import PageLinksGenerator, get_uuid_or_404, user_identity_required
from journal.models import (
Collection,
Comment,
Mark,
Review,
ShelfManager,
ShelfMember,
ShelfType,
q_piece_in_home_feed_of_user,
q_piece_visible_to_user,
)
from .forms import *
from .models import *
from .search.views import *
from .views_edit import *
NUM_REVIEWS_ON_ITEM_PAGE = 5
NUM_REVIEWS_ON_LIST_PAGE = 20
def retrieve_by_uuid(request, item_uid):
item = get_object_or_404(Item, uid=item_uid)
return redirect(item.url)
def retrieve_redirect(request, item_path, item_uuid):
return redirect(f"/{item_path}/{item_uuid}", permanent=True)
@require_http_methods(["GET"])
@xframe_options_exempt
def embed(request, item_path, item_uuid):
item = Item.get_by_url(item_uuid)
if item is None:
raise Http404(_("Item not found"))
if item.merged_to_item:
return redirect(item.merged_to_item.url)
if item.is_deleted:
raise Http404(_("Item no longer exists"))
focus_item = None
if request.GET.get("focus"):
focus_item = get_object_or_404(
Item, uid=get_uuid_or_404(request.GET.get("focus"))
)
return render(
request,
"embed_" + item.class_name + ".html",
{"item": item, "focus_item": focus_item},
)
@require_http_methods(["GET", "HEAD"])
@user_identity_required
def retrieve(request, item_path, item_uuid):
# item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
item = Item.get_by_url(item_uuid)
if item is None:
raise Http404(_("Item not found"))
item_url = f"/{item_path}/{item_uuid}"
if item.url != item_url:
return redirect(item.url)
skipcheck = request.GET.get("skipcheck", False) and request.user.is_authenticated
if not skipcheck and item.merged_to_item:
return redirect(item.merged_to_item.url)
if not skipcheck and item.is_deleted:
raise Http404(_("Item no longer exists"))
if request.headers.get("Accept", "").endswith("json"):
return redirect(item.api_url)
focus_item = None
if request.GET.get("focus"):
focus_item = get_object_or_404(
Item, uid=get_uuid_or_404(request.GET.get("focus"))
)
mark = None
review = None
my_collections = []
collection_list = []
child_item_comments = []
shelf_actions = ShelfManager.get_actions_for_category(item.category)
shelf_statuses = ShelfManager.get_statuses_for_category(item.category)
if request.user.is_authenticated:
visible = q_piece_visible_to_user(request.user)
mark = Mark(request.user.identity, item)
child_item_comments = Comment.objects.filter(
owner=request.user.identity, item__in=item.child_items.all()
)
review = mark.review
my_collections = item.collections.all().filter(owner=request.user.identity)
collection_list = (
item.collections.all()
.exclude(owner=request.user.identity)
.filter(visible)
.annotate(like_counts=Count("likes"))
.order_by("-like_counts")
)
else:
collection_list = (
item.collections.all()
.filter(visibility=0)
.annotate(like_counts=Count("likes"))
.order_by("-like_counts")
)
return render(
request,
item.class_name + ".html",
{
"item": item,
"focus_item": focus_item,
"mark": mark,
"review": review,
"child_item_comments": child_item_comments,
"my_collections": my_collections,
"collection_list": collection_list,
"shelf_actions": shelf_actions,
"shelf_statuses": shelf_statuses,
},
)
def episode_data(request, item_uuid):
item = get_object_or_404(Podcast, uid=get_uuid_or_404(item_uuid))
qs = item.episodes.all().order_by("-pub_date")
if request.GET.get("last"):
qs = qs.filter(pub_date__lt=request.GET.get("last"))
return render(
request, "podcast_episode_data.html", {"item": item, "episodes": qs[:5]}
)
@login_required
def mark_list(request, item_path, item_uuid, following_only=False):
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
queryset = ShelfMember.objects.filter(item=item).order_by("-created_time")
if following_only:
queryset = queryset.filter(q_piece_in_home_feed_of_user(request.user))
else:
queryset = queryset.filter(q_piece_visible_to_user(request.user))
paginator = Paginator(queryset, NUM_REVIEWS_ON_LIST_PAGE)
page_number = request.GET.get("page", default=1)
marks = paginator.get_page(page_number)
pagination = PageLinksGenerator(page_number, paginator.num_pages, request.GET)
return render(
request,
"item_mark_list.html",
{
"marks": marks,
"item": item,
"followeing_only": following_only,
"pagination": pagination,
},
)
def review_list(request, item_path, item_uuid):
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
queryset = Review.objects.filter(item=item).order_by("-created_time")
queryset = queryset.filter(q_piece_visible_to_user(request.user))
paginator = Paginator(queryset, NUM_REVIEWS_ON_LIST_PAGE)
page_number = request.GET.get("page", default=1)
reviews = paginator.get_page(page_number)
pagination = PageLinksGenerator(page_number, paginator.num_pages, request.GET)
return render(
request,
"item_review_list.html",
{
"reviews": reviews,
"item": item,
"pagination": pagination,
},
)
def comments(request, item_path, item_uuid):
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
ids = item.child_item_ids + [item.pk] + item.sibling_item_ids
queryset = Comment.objects.filter(item_id__in=ids).order_by("-created_time")
queryset = queryset.filter(q_piece_visible_to_user(request.user))
before_time = request.GET.get("last")
if before_time:
queryset = queryset.filter(created_time__lte=before_time)
return render(
request,
"_item_comments.html",
{
"item": item,
"comments": queryset[:11],
},
)
def comments_by_episode(request, item_path, item_uuid):
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
episode_uuid = request.GET.get("episode_uuid")
if episode_uuid:
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")
queryset = queryset.filter(q_piece_visible_to_user(request.user))
before_time = request.GET.get("last")
if before_time:
queryset = queryset.filter(created_time__lte=before_time)
return render(
request,
"_item_comments_by_episode.html",
{
"item": item,
"episode_uuid": episode_uuid,
"comments": queryset[:11],
},
)
def reviews(request, item_path, item_uuid):
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
ids = item.child_item_ids + [item.pk] + item.sibling_item_ids
queryset = Review.objects.filter(item_id__in=ids).order_by("-created_time")
queryset = queryset.filter(q_piece_visible_to_user(request.user))
before_time = request.GET.get("last")
if before_time:
queryset = queryset.filter(created_time__lte=before_time)
return render(
request,
"_item_reviews.html",
{
"item": item,
"reviews": queryset[:11],
},
)
@require_http_methods(["GET", "HEAD"])
def discover(request):
cache_key = "public_gallery"
gallery_list = cache.get(cache_key, [])
# rotate every 6 minutes
rot = timezone.now().minute // 6
for gallery in gallery_list:
i = rot * len(gallery["items"]) // 10
gallery["items"] = gallery["items"][i:] + gallery["items"][:i]
if request.user.is_authenticated:
if not request.user.registration_complete:
return redirect(reverse("users:register"))
layout = request.user.preference.discover_layout
identity = request.user.identity
else:
identity = None
layout = []
collection_ids = cache.get("featured_collections", [])
if collection_ids:
i = rot * len(collection_ids) // 10
collection_ids = collection_ids[i:] + collection_ids[:i]
featured_collections = Collection.objects.filter(pk__in=collection_ids)
else:
featured_collections = []
popular_tags = cache.get("popular_tags", [])
return render(
request,
"discover.html",
{
"identity": identity,
"gallery_list": gallery_list,
"featured_collections": featured_collections,
"popular_tags": popular_tags,
"layout": layout,
},
)