forked from mirrors/bookwyrm
Merge pull request #1845 from bookwyrm-social/organizing-templatetags
Organizing templatetags
This commit is contained in:
commit
db715cce2a
50 changed files with 630 additions and 375 deletions
|
@ -2,7 +2,7 @@
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load bookwyrm_tags %}
|
{% load landing_page_tags %}
|
||||||
{% load cache %}
|
{% load cache %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
|
|
||||||
{% get_book_file_links book as links %}
|
{% get_book_file_links book as links %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load rating_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load landing_page_tags %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends 'feed/layout.html' %}
|
{% extends 'feed/layout.html' %}
|
||||||
|
{% load feed_page_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
|
|
||||||
{% block opengraph_images %}
|
{% block opengraph_images %}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load feed_page_tags %}
|
||||||
|
|
||||||
{% suggested_books as suggested_books %}
|
{% suggested_books as suggested_books %}
|
||||||
<section class="block">
|
<section class="block">
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
{% extends 'groups/layout.html' %}
|
{% extends 'groups/layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load group_tags %}
|
||||||
{% load bookwyrm_group_tags %}
|
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
|
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load group_tags %}
|
||||||
|
|
||||||
{% block title %}{{ group.name }}{% endblock %}
|
{% block title %}{{ group.name }}{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load bookwyrm_tags %}
|
{% load group_tags %}
|
||||||
{% load bookwyrm_group_tags %}
|
|
||||||
|
|
||||||
<h2 class="title is-5">Group Members</h2>
|
<h2 class="title is-5">Group Members</h2>
|
||||||
{% if group.user == request.user %}
|
{% if group.user == request.user %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends 'landing/layout.html' %}
|
{% extends 'landing/layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load cache %}
|
{% load cache %}
|
||||||
{% load bookwyrm_tags %}
|
{% load landing_page_tags %}
|
||||||
|
|
||||||
{% block panel %}
|
{% block panel %}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
|
{% load rating_tags %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load rating_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% if book %}
|
{% if book %}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{% extends 'embed-layout.html' %}
|
{% extends 'embed-layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load rating_tags %}
|
||||||
|
{% load group_tags %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
|
|
||||||
{% block title %}{% blocktrans with list_name=list.name owner=list.user.display_name %}{{ list_name }}, a list by {{owner}}{% endblocktrans %}{% endblock title %}
|
{% block title %}{% blocktrans with list_name=list.name owner=list.user.display_name %}{{ list_name }}, a list by {{owner}}{% endblocktrans %}{% endblock title %}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{% extends 'lists/layout.html' %}
|
{% extends 'lists/layout.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load rating_tags %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load book_display_tags %}
|
||||||
|
{% load group_tags %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load notification_page_tags %}
|
||||||
{% related_status notification as related_status %}
|
{% related_status notification as related_status %}
|
||||||
<div class="notification {% if notification.id in unread %}has-background-primary{% endif %}">
|
<div class="notification {% if notification.id in unread %}has-background-primary{% endif %}">
|
||||||
<div class="columns is-mobile {% if notification.id in unread %}has-text-white{% else %}has-text-grey{% endif %}">
|
<div class="columns is-mobile {% if notification.id in unread %}has-text-white{% else %}has-text-grey{% endif %}">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% load bookwyrm_tags %}
|
{% load shelf_tags %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load group_tags %}
|
||||||
|
|
||||||
{% if request.user == user or not request.user == group.user or not request.user.is_authenticated %}
|
{% if request.user == user or not request.user == group.user or not request.user.is_authenticated %}
|
||||||
{% elif user in request.user.blocks.all %}
|
{% elif user in request.user.blocks.all %}
|
||||||
{% include 'snippets/block_button.html' with blocks=True %}
|
{% include 'snippets/block_button.html' with blocks=True %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "snippets/create_status/layout.html" %}
|
{% extends "snippets/create_status/layout.html" %}
|
||||||
{% load bookwyrm_tags %}
|
{% load shelf_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{% extends "snippets/create_status/layout.html" %}
|
{% extends "snippets/create_status/layout.html" %}
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{% extends "snippets/create_status/layout.html" %}
|
{% extends "snippets/create_status/layout.html" %}
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load status_display %}
|
{% load status_display %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load group_tags %}
|
||||||
|
|
||||||
{% if group|is_invited:request.user %}
|
{% if group|is_invited:request.user %}
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<form action="/accept-group-invitation/" method="POST">
|
<form action="/accept-group-invitation/" method="POST">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_tags %}
|
{% load rating_tags %}
|
||||||
|
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<span class="is-sr-only">{% trans "Leave a rating" %}</span>
|
<span class="is-sr-only">{% trans "Leave a rating" %}</span>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load group_tags %}
|
||||||
|
|
||||||
{% if request.user == user or not request.user == group.user or not request.user.is_authenticated %}
|
{% if request.user == user or not request.user == group.user or not request.user.is_authenticated %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if user in request.user.blocks.all %}
|
{% if user in request.user.blocks.all %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends 'components/dropdown.html' %}
|
{% extends 'components/dropdown.html' %}
|
||||||
{% load i18n %}
|
{% load shelf_tags %}
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% block dropdown-trigger %}
|
{% block dropdown-trigger %}
|
||||||
<span>{% trans "Move book" %}</span>
|
<span>{% trans "Move book" %}</span>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
|
{% load shelf_tags %}
|
||||||
|
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
|
{% load shelf_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
|
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% load bookwyrm_tags %}
|
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
|
{% load shelf_tags %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
|
{% with next_shelf_identifier=active_shelf.shelf.identifier|next_shelf %}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
|
{% load rating_tags %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
|
|
||||||
{% load bookwyrm_tags %}
|
{% load book_display_tags %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load cache %}
|
{% load cache %}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load markdown %}
|
{% load markdown %}
|
||||||
{% load layout %}
|
{% load layout %}
|
||||||
{% load bookwyrm_group_tags %}
|
{% load group_tags %}
|
||||||
|
|
||||||
{% block title %}{{ user.display_name }}{% endblock %}
|
{% block title %}{{ user.display_name }}{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load humanize %}
|
{% load humanize %}
|
||||||
{% load utilities %}
|
{% load utilities %}
|
||||||
{% load bookwyrm_tags %}
|
{% load user_page_tags %}
|
||||||
|
|
||||||
<div class="media block">
|
<div class="media block">
|
||||||
<div class="media-left">
|
<div class="media-left">
|
||||||
|
|
17
bookwyrm/templatetags/book_display_tags.py
Normal file
17
bookwyrm/templatetags/book_display_tags.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
""" template filters """
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
|
||||||
|
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.simple_tag(takes_context=False)
|
||||||
|
def get_book_file_links(book):
|
||||||
|
"""links for a book"""
|
||||||
|
return book.file_links.filter(domain__status="approved")
|
|
@ -1,226 +0,0 @@
|
||||||
""" template filters """
|
|
||||||
from django import template
|
|
||||||
from django.db.models import Avg, StdDev, Count, F, Q
|
|
||||||
|
|
||||||
from bookwyrm import models
|
|
||||||
from bookwyrm.utils import cache
|
|
||||||
from bookwyrm.views.feed import get_suggested_books
|
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter(name="rating")
|
|
||||||
def get_rating(book, user):
|
|
||||||
"""get the overall rating of a book"""
|
|
||||||
return cache.get_or_set(
|
|
||||||
f"book-rating-{book.parent_work.id}-{user.id}",
|
|
||||||
lambda u, b: models.Review.privacy_filter(u)
|
|
||||||
.filter(book__parent_work__editions=b)
|
|
||||||
.aggregate(Avg("rating"))["rating__avg"]
|
|
||||||
or 0,
|
|
||||||
user,
|
|
||||||
book,
|
|
||||||
timeout=15552000,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter(name="user_rating")
|
|
||||||
def get_user_rating(book, user):
|
|
||||||
"""get a user's rating of a book"""
|
|
||||||
rating = (
|
|
||||||
models.Review.objects.filter(
|
|
||||||
user=user,
|
|
||||||
book=book,
|
|
||||||
rating__isnull=False,
|
|
||||||
deleted=False,
|
|
||||||
)
|
|
||||||
.order_by("-published_date")
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
if rating:
|
|
||||||
return rating.rating
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter(name="is_book_on_shelf")
|
|
||||||
def get_is_book_on_shelf(book, shelf):
|
|
||||||
"""is a book on a shelf"""
|
|
||||||
return cache.get_or_set(
|
|
||||||
f"book-on-shelf-{book.id}-{shelf.id}",
|
|
||||||
lambda b, s: s.books.filter(id=b.id).exists(),
|
|
||||||
book,
|
|
||||||
shelf,
|
|
||||||
timeout=15552000,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@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="next_shelf")
|
|
||||||
def get_next_shelf(current_shelf):
|
|
||||||
"""shelf you'd use to update reading progress"""
|
|
||||||
if current_shelf == "to-read":
|
|
||||||
return "reading"
|
|
||||||
if current_shelf == "reading":
|
|
||||||
return "read"
|
|
||||||
if current_shelf == "read":
|
|
||||||
return "complete"
|
|
||||||
return "to-read"
|
|
||||||
|
|
||||||
|
|
||||||
@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=True)
|
|
||||||
def active_shelf(context, book):
|
|
||||||
"""check what shelf a user has a book on, if any"""
|
|
||||||
user = context["request"].user
|
|
||||||
return (
|
|
||||||
cache.get_or_set(
|
|
||||||
f"active_shelf-{user.id}-{book.id}",
|
|
||||||
lambda u, b: (
|
|
||||||
models.ShelfBook.objects.filter(
|
|
||||||
shelf__user=u,
|
|
||||||
book__parent_work__editions=b,
|
|
||||||
).first()
|
|
||||||
or False
|
|
||||||
),
|
|
||||||
user,
|
|
||||||
book,
|
|
||||||
timeout=15552000,
|
|
||||||
)
|
|
||||||
or {"book": book}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=False)
|
|
||||||
def latest_read_through(book, user):
|
|
||||||
"""the most recent read activity"""
|
|
||||||
return cache.get_or_set(
|
|
||||||
f"latest_read_through-{user.id}-{book.id}",
|
|
||||||
lambda u, b: (
|
|
||||||
models.ReadThrough.objects.filter(user=u, book=b, is_active=True)
|
|
||||||
.order_by("-start_date")
|
|
||||||
.first()
|
|
||||||
or False
|
|
||||||
),
|
|
||||||
user,
|
|
||||||
book,
|
|
||||||
timeout=15552000,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@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")
|
|
28
bookwyrm/templatetags/feed_page_tags.py
Normal file
28
bookwyrm/templatetags/feed_page_tags.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
""" tags used on the feed pages """
|
||||||
|
from django import template
|
||||||
|
from bookwyrm.views.feed import get_suggested_books
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@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=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)
|
76
bookwyrm/templatetags/landing_page_tags.py
Normal file
76
bookwyrm/templatetags/landing_page_tags.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
""" template filters """
|
||||||
|
from django import template
|
||||||
|
from django.db.models import Avg, StdDev, Count, F, Q
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@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 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]
|
||||||
|
)
|
||||||
|
)
|
14
bookwyrm/templatetags/notification_page_tags.py
Normal file
14
bookwyrm/templatetags/notification_page_tags.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
""" tags used on the feed pages """
|
||||||
|
from django import template
|
||||||
|
from bookwyrm.templatetags.feed_page_tags import load_subclass
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@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)
|
42
bookwyrm/templatetags/rating_tags.py
Normal file
42
bookwyrm/templatetags/rating_tags.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
""" template filters """
|
||||||
|
from django import template
|
||||||
|
from django.db.models import Avg
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.utils import cache
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name="rating")
|
||||||
|
def get_rating(book, user):
|
||||||
|
"""get the overall rating of a book"""
|
||||||
|
return cache.get_or_set(
|
||||||
|
f"book-rating-{book.parent_work.id}-{user.id}",
|
||||||
|
lambda u, b: models.Review.privacy_filter(u)
|
||||||
|
.filter(book__parent_work__editions=b, rating__gt=0)
|
||||||
|
.aggregate(Avg("rating"))["rating__avg"]
|
||||||
|
or 0,
|
||||||
|
user,
|
||||||
|
book,
|
||||||
|
timeout=15552000,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name="user_rating")
|
||||||
|
def get_user_rating(book, user):
|
||||||
|
"""get a user's rating of a book"""
|
||||||
|
rating = (
|
||||||
|
models.Review.objects.filter(
|
||||||
|
user=user,
|
||||||
|
book=book,
|
||||||
|
rating__isnull=False,
|
||||||
|
deleted=False,
|
||||||
|
)
|
||||||
|
.order_by("-published_date")
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if rating:
|
||||||
|
return rating.rating
|
||||||
|
return 0
|
71
bookwyrm/templatetags/shelf_tags.py
Normal file
71
bookwyrm/templatetags/shelf_tags.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
""" Filters and tags related to shelving books """
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.utils import cache
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name="is_book_on_shelf")
|
||||||
|
def get_is_book_on_shelf(book, shelf):
|
||||||
|
"""is a book on a shelf"""
|
||||||
|
return cache.get_or_set(
|
||||||
|
f"book-on-shelf-{book.id}-{shelf.id}",
|
||||||
|
lambda b, s: s.books.filter(id=b.id).exists(),
|
||||||
|
book,
|
||||||
|
shelf,
|
||||||
|
timeout=15552000,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name="next_shelf")
|
||||||
|
def get_next_shelf(current_shelf):
|
||||||
|
"""shelf you'd use to update reading progress"""
|
||||||
|
if current_shelf == "to-read":
|
||||||
|
return "reading"
|
||||||
|
if current_shelf == "reading":
|
||||||
|
return "read"
|
||||||
|
if current_shelf == "read":
|
||||||
|
return "complete"
|
||||||
|
return "to-read"
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=True)
|
||||||
|
def active_shelf(context, book):
|
||||||
|
"""check what shelf a user has a book on, if any"""
|
||||||
|
user = context["request"].user
|
||||||
|
return (
|
||||||
|
cache.get_or_set(
|
||||||
|
f"active_shelf-{user.id}-{book.id}",
|
||||||
|
lambda u, b: (
|
||||||
|
models.ShelfBook.objects.filter(
|
||||||
|
shelf__user=u,
|
||||||
|
book__parent_work__editions=b,
|
||||||
|
).first()
|
||||||
|
or False
|
||||||
|
),
|
||||||
|
user,
|
||||||
|
book,
|
||||||
|
timeout=15552000,
|
||||||
|
)
|
||||||
|
or {"book": book}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag(takes_context=False)
|
||||||
|
def latest_read_through(book, user):
|
||||||
|
"""the most recent read activity"""
|
||||||
|
return cache.get_or_set(
|
||||||
|
f"latest_read_through-{user.id}-{book.id}",
|
||||||
|
lambda u, b: (
|
||||||
|
models.ReadThrough.objects.filter(user=u, book=b, is_active=True)
|
||||||
|
.order_by("-start_date")
|
||||||
|
.first()
|
||||||
|
or False
|
||||||
|
),
|
||||||
|
user,
|
||||||
|
book,
|
||||||
|
timeout=15552000,
|
||||||
|
)
|
14
bookwyrm/templatetags/user_page_tags.py
Normal file
14
bookwyrm/templatetags/user_page_tags.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
""" template filters """
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@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()
|
62
bookwyrm/tests/templatetags/test_book_display_tags.py
Normal file
62
bookwyrm/tests/templatetags/test_book_display_tags.py
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
""" style fixes and lookups for templates """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.templatetags import book_display_tags
|
||||||
|
|
||||||
|
|
||||||
|
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||||
|
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
||||||
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
|
class BookDisplayTags(TestCase):
|
||||||
|
"""lotta different things here"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""create some filler objects"""
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.user = models.User.objects.create_user(
|
||||||
|
"mouse@example.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"mouseword",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
self.book = models.Edition.objects.create(title="Test Book")
|
||||||
|
|
||||||
|
def test_get_book_description(self, *_):
|
||||||
|
"""grab it from the edition or the parent"""
|
||||||
|
work = models.Work.objects.create(title="Test Work")
|
||||||
|
self.book.parent_work = work
|
||||||
|
self.book.save()
|
||||||
|
|
||||||
|
self.assertIsNone(book_display_tags.get_book_description(self.book))
|
||||||
|
|
||||||
|
work.description = "hi"
|
||||||
|
work.save()
|
||||||
|
self.assertEqual(book_display_tags.get_book_description(self.book), "hi")
|
||||||
|
|
||||||
|
self.book.description = "hello"
|
||||||
|
self.book.save()
|
||||||
|
self.assertEqual(book_display_tags.get_book_description(self.book), "hello")
|
||||||
|
|
||||||
|
def test_get_book_file_links(self, *_):
|
||||||
|
"""load approved links"""
|
||||||
|
link = models.FileLink.objects.create(
|
||||||
|
book=self.book,
|
||||||
|
url="https://web.site/hello",
|
||||||
|
)
|
||||||
|
links = book_display_tags.get_book_file_links(self.book)
|
||||||
|
# the link is pending
|
||||||
|
self.assertFalse(links.exists())
|
||||||
|
|
||||||
|
domain = link.domain
|
||||||
|
domain.status = "approved"
|
||||||
|
domain.save()
|
||||||
|
|
||||||
|
links = book_display_tags.get_book_file_links(self.book)
|
||||||
|
self.assertTrue(links.exists())
|
||||||
|
self.assertEqual(links[0], link)
|
|
@ -1,101 +0,0 @@
|
||||||
""" style fixes and lookups for templates """
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
from bookwyrm import models
|
|
||||||
from bookwyrm.templatetags import bookwyrm_tags
|
|
||||||
|
|
||||||
|
|
||||||
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
|
||||||
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
|
||||||
class BookWyrmTags(TestCase):
|
|
||||||
"""lotta different things here"""
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
"""create some filler objects"""
|
|
||||||
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
|
||||||
"bookwyrm.activitystreams.populate_stream_task.delay"
|
|
||||||
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
|
||||||
self.user = models.User.objects.create_user(
|
|
||||||
"mouse@example.com",
|
|
||||||
"mouse@mouse.mouse",
|
|
||||||
"mouseword",
|
|
||||||
local=True,
|
|
||||||
localname="mouse",
|
|
||||||
)
|
|
||||||
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
|
||||||
self.remote_user = models.User.objects.create_user(
|
|
||||||
"rat",
|
|
||||||
"rat@rat.rat",
|
|
||||||
"ratword",
|
|
||||||
remote_id="http://example.com/rat",
|
|
||||||
local=False,
|
|
||||||
)
|
|
||||||
self.book = models.Edition.objects.create(title="Test Book")
|
|
||||||
|
|
||||||
def test_get_user_rating(self, *_):
|
|
||||||
"""get a user's most recent rating of a book"""
|
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
|
|
||||||
models.Review.objects.create(user=self.user, book=self.book, rating=3)
|
|
||||||
self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 3)
|
|
||||||
|
|
||||||
def test_get_user_rating_doesnt_exist(self, *_):
|
|
||||||
"""there is no rating available"""
|
|
||||||
self.assertEqual(bookwyrm_tags.get_user_rating(self.book, self.user), 0)
|
|
||||||
|
|
||||||
def test_get_book_description(self, *_):
|
|
||||||
"""grab it from the edition or the parent"""
|
|
||||||
work = models.Work.objects.create(title="Test Work")
|
|
||||||
self.book.parent_work = work
|
|
||||||
self.book.save()
|
|
||||||
|
|
||||||
self.assertIsNone(bookwyrm_tags.get_book_description(self.book))
|
|
||||||
|
|
||||||
work.description = "hi"
|
|
||||||
work.save()
|
|
||||||
self.assertEqual(bookwyrm_tags.get_book_description(self.book), "hi")
|
|
||||||
|
|
||||||
self.book.description = "hello"
|
|
||||||
self.book.save()
|
|
||||||
self.assertEqual(bookwyrm_tags.get_book_description(self.book), "hello")
|
|
||||||
|
|
||||||
def test_get_next_shelf(self, *_):
|
|
||||||
"""self progress helper"""
|
|
||||||
self.assertEqual(bookwyrm_tags.get_next_shelf("to-read"), "reading")
|
|
||||||
self.assertEqual(bookwyrm_tags.get_next_shelf("reading"), "read")
|
|
||||||
self.assertEqual(bookwyrm_tags.get_next_shelf("read"), "complete")
|
|
||||||
self.assertEqual(bookwyrm_tags.get_next_shelf("blooooga"), "to-read")
|
|
||||||
|
|
||||||
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
|
||||||
def test_load_subclass(self, *_):
|
|
||||||
"""get a status' real type"""
|
|
||||||
review = models.Review.objects.create(user=self.user, book=self.book, rating=3)
|
|
||||||
status = models.Status.objects.get(id=review.id)
|
|
||||||
self.assertIsInstance(status, models.Status)
|
|
||||||
self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Review)
|
|
||||||
|
|
||||||
quote = models.Quotation.objects.create(
|
|
||||||
user=self.user, book=self.book, content="hi"
|
|
||||||
)
|
|
||||||
status = models.Status.objects.get(id=quote.id)
|
|
||||||
self.assertIsInstance(status, models.Status)
|
|
||||||
self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Quotation)
|
|
||||||
|
|
||||||
comment = models.Comment.objects.create(
|
|
||||||
user=self.user, book=self.book, content="hi"
|
|
||||||
)
|
|
||||||
status = models.Status.objects.get(id=comment.id)
|
|
||||||
self.assertIsInstance(status, models.Status)
|
|
||||||
self.assertIsInstance(bookwyrm_tags.load_subclass(status), models.Comment)
|
|
||||||
|
|
||||||
def test_related_status(self, *_):
|
|
||||||
"""gets the subclass model for a notification status"""
|
|
||||||
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
|
|
||||||
status = models.Status.objects.create(content="hi", user=self.user)
|
|
||||||
notification = models.Notification.objects.create(
|
|
||||||
user=self.user, notification_type="MENTION", related_status=status
|
|
||||||
)
|
|
||||||
|
|
||||||
result = bookwyrm_tags.related_status(notification)
|
|
||||||
self.assertIsInstance(result, models.Status)
|
|
49
bookwyrm/tests/templatetags/test_feed_page_tags.py
Normal file
49
bookwyrm/tests/templatetags/test_feed_page_tags.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
""" style fixes and lookups for templates """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.templatetags import feed_page_tags
|
||||||
|
|
||||||
|
|
||||||
|
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||||
|
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
||||||
|
class FeedPageTags(TestCase):
|
||||||
|
"""lotta different things here"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""create some filler objects"""
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.user = models.User.objects.create_user(
|
||||||
|
"mouse@example.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"mouseword",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
self.book = models.Edition.objects.create(title="Test Book")
|
||||||
|
|
||||||
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
|
def test_load_subclass(self, *_):
|
||||||
|
"""get a status' real type"""
|
||||||
|
review = models.Review.objects.create(user=self.user, book=self.book, rating=3)
|
||||||
|
status = models.Status.objects.get(id=review.id)
|
||||||
|
self.assertIsInstance(status, models.Status)
|
||||||
|
self.assertIsInstance(feed_page_tags.load_subclass(status), models.Review)
|
||||||
|
|
||||||
|
quote = models.Quotation.objects.create(
|
||||||
|
user=self.user, book=self.book, content="hi"
|
||||||
|
)
|
||||||
|
status = models.Status.objects.get(id=quote.id)
|
||||||
|
self.assertIsInstance(status, models.Status)
|
||||||
|
self.assertIsInstance(feed_page_tags.load_subclass(status), models.Quotation)
|
||||||
|
|
||||||
|
comment = models.Comment.objects.create(
|
||||||
|
user=self.user, book=self.book, content="hi"
|
||||||
|
)
|
||||||
|
status = models.Status.objects.get(id=comment.id)
|
||||||
|
self.assertIsInstance(status, models.Status)
|
||||||
|
self.assertIsInstance(feed_page_tags.load_subclass(status), models.Comment)
|
37
bookwyrm/tests/templatetags/test_notification_page_tags.py
Normal file
37
bookwyrm/tests/templatetags/test_notification_page_tags.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
""" style fixes and lookups for templates """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.templatetags import notification_page_tags
|
||||||
|
|
||||||
|
|
||||||
|
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||||
|
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
||||||
|
class NotificationPageTags(TestCase):
|
||||||
|
"""lotta different things here"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""create some filler objects"""
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.user = models.User.objects.create_user(
|
||||||
|
"mouse@example.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"mouseword",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_related_status(self, *_):
|
||||||
|
"""gets the subclass model for a notification status"""
|
||||||
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
|
||||||
|
status = models.Status.objects.create(content="hi", user=self.user)
|
||||||
|
notification = models.Notification.objects.create(
|
||||||
|
user=self.user, notification_type="MENTION", related_status=status
|
||||||
|
)
|
||||||
|
|
||||||
|
result = notification_page_tags.related_status(notification)
|
||||||
|
self.assertIsInstance(result, models.Status)
|
80
bookwyrm/tests/templatetags/test_rating_tags.py
Normal file
80
bookwyrm/tests/templatetags/test_rating_tags.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
""" Gettings book ratings """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.templatetags import rating_tags
|
||||||
|
|
||||||
|
|
||||||
|
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||||
|
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
||||||
|
class RatingTags(TestCase):
|
||||||
|
"""lotta different things here"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""create some filler objects"""
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.local_user = models.User.objects.create_user(
|
||||||
|
"mouse@example.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"mouseword",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||||
|
self.remote_user = models.User.objects.create_user(
|
||||||
|
"rat",
|
||||||
|
"rat@rat.rat",
|
||||||
|
"ratword",
|
||||||
|
remote_id="http://example.com/rat",
|
||||||
|
local=False,
|
||||||
|
)
|
||||||
|
work = models.Work.objects.create(title="Work title")
|
||||||
|
self.book = models.Edition.objects.create(
|
||||||
|
title="Test Book",
|
||||||
|
parent_work=work,
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
|
def test_get_rating(self, *_):
|
||||||
|
"""privacy filtered rating"""
|
||||||
|
# follows-only: not included
|
||||||
|
models.ReviewRating.objects.create(
|
||||||
|
user=self.remote_user,
|
||||||
|
rating=5,
|
||||||
|
book=self.book,
|
||||||
|
privacy="followers",
|
||||||
|
)
|
||||||
|
self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 0)
|
||||||
|
|
||||||
|
# public: included
|
||||||
|
models.ReviewRating.objects.create(
|
||||||
|
user=self.remote_user,
|
||||||
|
rating=5,
|
||||||
|
book=self.book,
|
||||||
|
privacy="public",
|
||||||
|
)
|
||||||
|
self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 5)
|
||||||
|
|
||||||
|
# rating unset: not included
|
||||||
|
models.Review.objects.create(
|
||||||
|
name="blah",
|
||||||
|
user=self.local_user,
|
||||||
|
rating=0,
|
||||||
|
book=self.book,
|
||||||
|
privacy="public",
|
||||||
|
)
|
||||||
|
self.assertEqual(rating_tags.get_rating(self.book, self.local_user), 5)
|
||||||
|
|
||||||
|
def test_get_user_rating(self, *_):
|
||||||
|
"""get a user's most recent rating of a book"""
|
||||||
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"):
|
||||||
|
models.Review.objects.create(user=self.local_user, book=self.book, rating=3)
|
||||||
|
self.assertEqual(rating_tags.get_user_rating(self.book, self.local_user), 3)
|
||||||
|
|
||||||
|
def test_get_user_rating_doesnt_exist(self, *_):
|
||||||
|
"""there is no rating available"""
|
||||||
|
self.assertEqual(rating_tags.get_user_rating(self.book, self.local_user), 0)
|
70
bookwyrm/tests/templatetags/test_shelf_tags.py
Normal file
70
bookwyrm/tests/templatetags/test_shelf_tags.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
""" style fixes and lookups for templates """
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.client import RequestFactory
|
||||||
|
|
||||||
|
from bookwyrm import models
|
||||||
|
from bookwyrm.templatetags import shelf_tags
|
||||||
|
|
||||||
|
|
||||||
|
@patch("bookwyrm.activitystreams.add_status_task.delay")
|
||||||
|
@patch("bookwyrm.activitystreams.remove_status_task.delay")
|
||||||
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
|
@patch("bookwyrm.activitystreams.add_book_statuses_task.delay")
|
||||||
|
class ShelfTags(TestCase):
|
||||||
|
"""lotta different things here"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""create some filler objects"""
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"), patch(
|
||||||
|
"bookwyrm.activitystreams.populate_stream_task.delay"
|
||||||
|
), patch("bookwyrm.lists_stream.populate_lists_task.delay"):
|
||||||
|
self.local_user = models.User.objects.create_user(
|
||||||
|
"mouse@example.com",
|
||||||
|
"mouse@mouse.mouse",
|
||||||
|
"mouseword",
|
||||||
|
local=True,
|
||||||
|
localname="mouse",
|
||||||
|
)
|
||||||
|
with patch("bookwyrm.models.user.set_remote_server.delay"):
|
||||||
|
self.remote_user = models.User.objects.create_user(
|
||||||
|
"rat",
|
||||||
|
"rat@rat.rat",
|
||||||
|
"ratword",
|
||||||
|
remote_id="http://example.com/rat",
|
||||||
|
local=False,
|
||||||
|
)
|
||||||
|
self.book = models.Edition.objects.create(
|
||||||
|
title="Test Book",
|
||||||
|
parent_work=models.Work.objects.create(title="Test work"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_get_is_book_on_shelf(self, *_):
|
||||||
|
"""check if a book is on a shelf"""
|
||||||
|
shelf = self.local_user.shelf_set.first()
|
||||||
|
self.assertFalse(shelf_tags.get_is_book_on_shelf(self.book, shelf))
|
||||||
|
models.ShelfBook.objects.create(
|
||||||
|
shelf=shelf, book=self.book, user=self.local_user
|
||||||
|
)
|
||||||
|
self.assertTrue(shelf_tags.get_is_book_on_shelf(self.book, shelf))
|
||||||
|
|
||||||
|
def test_get_next_shelf(self, *_):
|
||||||
|
"""self progress helper"""
|
||||||
|
self.assertEqual(shelf_tags.get_next_shelf("to-read"), "reading")
|
||||||
|
self.assertEqual(shelf_tags.get_next_shelf("reading"), "read")
|
||||||
|
self.assertEqual(shelf_tags.get_next_shelf("read"), "complete")
|
||||||
|
self.assertEqual(shelf_tags.get_next_shelf("blooooga"), "to-read")
|
||||||
|
|
||||||
|
def test_active_shelf(self, *_):
|
||||||
|
"""get the shelf a book is on"""
|
||||||
|
shelf = self.local_user.shelf_set.first()
|
||||||
|
request = self.factory.get("")
|
||||||
|
request.user = self.local_user
|
||||||
|
context = {"request": request}
|
||||||
|
self.assertIsInstance(shelf_tags.active_shelf(context, self.book), dict)
|
||||||
|
models.ShelfBook.objects.create(
|
||||||
|
shelf=shelf, book=self.book, user=self.local_user
|
||||||
|
)
|
||||||
|
self.assertEqual(shelf_tags.active_shelf(context, self.book).shelf, shelf)
|
|
@ -1,4 +1,5 @@
|
||||||
""" style fixes and lookups for templates """
|
""" style fixes and lookups for templates """
|
||||||
|
from datetime import datetime
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -35,6 +36,12 @@ class StatusDisplayTags(TestCase):
|
||||||
)
|
)
|
||||||
self.book = models.Edition.objects.create(title="Test Book")
|
self.book = models.Edition.objects.create(title="Test Book")
|
||||||
|
|
||||||
|
def test_get_mentions(self, *_):
|
||||||
|
"""list of people mentioned"""
|
||||||
|
status = models.Status.objects.create(content="hi", user=self.remote_user)
|
||||||
|
result = status_display.get_mentions(status, self.user)
|
||||||
|
self.assertEqual(result, "@rat@example.com ")
|
||||||
|
|
||||||
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
@patch("bookwyrm.models.activitypub_mixin.broadcast_task.apply_async")
|
||||||
def test_get_replies(self, *_):
|
def test_get_replies(self, *_):
|
||||||
"""direct replies to a status"""
|
"""direct replies to a status"""
|
||||||
|
@ -83,8 +90,16 @@ class StatusDisplayTags(TestCase):
|
||||||
self.assertIsInstance(boosted, models.Review)
|
self.assertIsInstance(boosted, models.Review)
|
||||||
self.assertEqual(boosted, status)
|
self.assertEqual(boosted, status)
|
||||||
|
|
||||||
def test_get_mentions(self, *_):
|
def test_get_published_date(self, *_):
|
||||||
"""list of people mentioned"""
|
"""date formatting"""
|
||||||
status = models.Status.objects.create(content="hi", user=self.remote_user)
|
date = datetime(2020, 1, 1, 0, 0, tzinfo=timezone.utc)
|
||||||
result = status_display.get_mentions(status, self.user)
|
with patch("django.utils.timezone.now") as timezone_mock:
|
||||||
self.assertEqual(result, "@rat@example.com ")
|
timezone_mock.return_value = datetime(2022, 1, 1, 0, 0, tzinfo=timezone.utc)
|
||||||
|
result = status_display.get_published_date(date)
|
||||||
|
self.assertEqual(result, "Jan. 1, 2020")
|
||||||
|
|
||||||
|
date = datetime(2022, 1, 1, 0, 0, tzinfo=timezone.utc)
|
||||||
|
with patch("django.utils.timezone.now") as timezone_mock:
|
||||||
|
timezone_mock.return_value = datetime(2022, 1, 8, 0, 0, tzinfo=timezone.utc)
|
||||||
|
result = status_display.get_published_date(date)
|
||||||
|
self.assertEqual(result, "Jan 1")
|
||||||
|
|
|
@ -35,6 +35,15 @@ class UtilitiesTags(TestCase):
|
||||||
)
|
)
|
||||||
self.book = models.Edition.objects.create(title="Test Book")
|
self.book = models.Edition.objects.create(title="Test Book")
|
||||||
|
|
||||||
|
def test_get_uuid(self, *_):
|
||||||
|
"""uuid functionality"""
|
||||||
|
uuid = utilities.get_uuid("hi")
|
||||||
|
self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
|
||||||
|
|
||||||
|
def test_join(self, *_):
|
||||||
|
"""concats things with underscores"""
|
||||||
|
self.assertEqual(utilities.join("hi", 5, "blah", 0.75), "hi_5_blah_0.75")
|
||||||
|
|
||||||
def test_get_user_identifer_local(self, *_):
|
def test_get_user_identifer_local(self, *_):
|
||||||
"""fall back to the simplest uid available"""
|
"""fall back to the simplest uid available"""
|
||||||
self.assertNotEqual(self.user.username, self.user.localname)
|
self.assertNotEqual(self.user.username, self.user.localname)
|
||||||
|
@ -46,11 +55,6 @@ class UtilitiesTags(TestCase):
|
||||||
utilities.get_user_identifier(self.remote_user), "rat@example.com"
|
utilities.get_user_identifier(self.remote_user), "rat@example.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_get_uuid(self, *_):
|
|
||||||
"""uuid functionality"""
|
|
||||||
uuid = utilities.get_uuid("hi")
|
|
||||||
self.assertTrue(re.match(r"hi[A-Za-z0-9\-]", uuid))
|
|
||||||
|
|
||||||
def test_get_title(self, *_):
|
def test_get_title(self, *_):
|
||||||
"""the title of a book"""
|
"""the title of a book"""
|
||||||
self.assertEqual(utilities.get_title(None), "")
|
self.assertEqual(utilities.get_title(None), "")
|
||||||
|
|
Loading…
Reference in a new issue