""" template filters """ from django import template from django.db.models import Avg, StdDev, Count, F, Q from bookwyrm import models from bookwyrm.views.feed import get_suggested_books register = template.Library() @register.filter(name="book_description") def get_book_description(book): """use the work's text if the book doesn't have it""" return book.description or book.parent_work.description @register.filter(name="load_subclass") def load_subclass(status): """sometimes you didn't select_subclass""" if hasattr(status, "quotation"): return status.quotation if hasattr(status, "review"): return status.review if hasattr(status, "comment"): return status.comment if hasattr(status, "generatednote"): return status.generatednote return status @register.simple_tag(takes_context=False) def get_book_superlatives(): """get book stats for the about page""" total_ratings = models.Review.objects.filter(local=True, deleted=False).count() data = {} data["top_rated"] = ( models.Work.objects.annotate( rating=Avg( "editions__review__rating", filter=Q(editions__review__local=True, editions__review__deleted=False), ), rating_count=Count( "editions__review", filter=Q(editions__review__local=True, editions__review__deleted=False), ), ) .annotate(weighted=F("rating") * F("rating_count") / total_ratings) .filter(rating__gt=4, weighted__gt=0) .order_by("-weighted") .first() ) data["controversial"] = ( models.Work.objects.annotate( deviation=StdDev( "editions__review__rating", filter=Q(editions__review__local=True, editions__review__deleted=False), ), rating_count=Count( "editions__review", filter=Q(editions__review__local=True, editions__review__deleted=False), ), ) .annotate(weighted=F("deviation") * F("rating_count") / total_ratings) .filter(weighted__gt=0) .order_by("-weighted") .first() ) data["wanted"] = ( models.Work.objects.annotate( shelf_count=Count( "editions__shelves", filter=Q(editions__shelves__identifier="to-read") ) ) .order_by("-shelf_count") .first() ) return data @register.simple_tag(takes_context=False) def related_status(notification): """for notifications""" if not notification.related_status: return None return load_subclass(notification.related_status) @register.simple_tag(takes_context=False) def get_landing_books(): """list of books for the landing page""" return list( set( models.Edition.objects.filter( review__published_date__isnull=False, review__deleted=False, review__user__local=True, review__privacy__in=["public", "unlisted"], ) .exclude(cover__exact="") .distinct() .order_by("-review__published_date")[:6] ) ) @register.simple_tag(takes_context=True) def mutuals_count(context, user): """how many users that you follow, follow them""" viewer = context["request"].user if not viewer.is_authenticated: return None return user.followers.filter(followers=viewer).count() @register.simple_tag(takes_context=True) def suggested_books(context): """get books for suggested books panel""" # this happens here instead of in the view so that the template snippet can # be cached in the template return get_suggested_books(context["request"].user) @register.simple_tag(takes_context=False) def get_book_file_links(book): """links for a book""" return book.file_links.filter(domain__status="approved")