Skip to content

Commit

Permalink
Cache the ingredient list view and increase count method (only postgres)
Browse files Browse the repository at this point in the history
While this caches the whole page and not parts of it (so things like the
currently logged user will be shown), this should get us some breathing room
while we find a permanent solution
  • Loading branch information
rolandgeider committed Jun 14, 2024
1 parent eb14b3d commit e68afe7
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 22 deletions.
35 changes: 19 additions & 16 deletions wger/core/templates/tags/pagination.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
<ul class="pagination justify-content-center">
{% if page.has_previous %}
<li class="page-item">
<a href="?page={{ page.previous_page_number }}"
class="load-maincontent page-link">« {% translate "previous" %}</a>
<a href="?page={{ page.previous_page_number }}" class="page-link">
« {% translate "previous" %}
</a>
</li>
{% else %}
<li class="page-item disabled">
Expand All @@ -15,25 +16,27 @@
{% for i in page_range %}
{% if page.number != i %}
<li class="page-item">
<a href="?page={{ i }}"
class="load-maincontent page-link">{{i}}</a>
</li>
<a href="?page={{ i }}" class="page-link">
{{ i }}
</a>
</li>
{% else %}
<li class="page-item active">
<a href="#" class="page-link">{{i}}</a>
<a href="#" class="page-link">{{ i }}</a>
</li>
{% endif %}
{% endfor %}

{% if page.has_next %}
<li class="page-item">
<a href="?page={{ page.next_page_number }}"
class="load-maincontent page-link">{%trans "next" %} »</a>
</li>
{% else %}
<li class="page-item disabled">
<a href="#" class="page-link">{%trans "next" %} »</a>
</li>
{% endif %}
{% if page.has_next %}
<li class="page-item">
<a href="?page={{ page.next_page_number }}" class="page-link">
{% trans "next" %} »
</a>
</li>
{% else %}
<li class="page-item disabled">
<a href="#" class="page-link">{% trans "next" %} »</a>
</li>
{% endif %}
</ul>

55 changes: 55 additions & 0 deletions wger/nutrition/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This file is part of wger Workout Manager <https://github.com/wger-project>.
# Copyright (C) wger Team
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

# Django
from django.conf import settings
from django.db import connections
from django.db.models import (
Manager,
QuerySet,
)

# wger
from wger.utils.db import is_postgres_db


class ApproximateCountQuerySet(QuerySet):
"""
Approximate count query set, postgreSQL only
While this doesn't return an exact count, it does return an approximate
in a much shorter amount of time, which is specially important for the
ingredients
https://testdriven.io/blog/django-approximate-counting/
"""

def count(self):
if self.query.where:
return super(ApproximateCountQuerySet, self).count()

if is_postgres_db() and not settings.TESTING:
cursor = connections[self.db].cursor()
cursor.execute(
"SELECT reltuples FROM pg_class WHERE relname = '%s';" % self.model._meta.db_table
)

return int(cursor.fetchone()[0])

return super(ApproximateCountQuerySet, self).count()


ApproximateCountManager = Manager.from_queryset(ApproximateCountQuerySet)
7 changes: 4 additions & 3 deletions wger/nutrition/models/ingredient.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,15 @@
ENERGY_FACTOR,
KJ_PER_KCAL,
)
from wger.nutrition.managers import ApproximateCountManager
from wger.nutrition.models.ingredient_category import IngredientCategory
from wger.nutrition.models.sources import Source
from wger.utils.cache import cache_mapper
from wger.utils.constants import TWOPLACES
from wger.utils.language import load_language
from wger.utils.models import AbstractLicenseModel
from wger.utils.requests import wger_user_agent

# Local
from .ingredient_category import IngredientCategory


logger = logging.getLogger(__name__)

Expand All @@ -75,6 +74,8 @@ class Ingredient(AbstractLicenseModel, models.Model):
energy amount given (in percent).
"""

objects = ApproximateCountManager()

language = models.ForeignKey(
Language,
verbose_name=_('Language'),
Expand Down
4 changes: 2 additions & 2 deletions wger/nutrition/templates/ingredient/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
{% endif %}


{# <div style="padding-top:3em;"></div> #}
{# {% pagination paginator page_obj %} #}
<div style="padding-top:3em;"></div>
{% pagination paginator page_obj %}
{% endblock %}

{% block sidebar %}
Expand Down
8 changes: 7 additions & 1 deletion wger/nutrition/views/ingredient.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import logging

# Django
from django.conf import settings
from django.contrib.auth.mixins import (
LoginRequiredMixin,
PermissionRequiredMixin,
Expand All @@ -29,10 +30,12 @@
render,
)
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import (
gettext as _,
gettext_lazy,
)
from django.views.decorators.cache import cache_page
from django.views.generic import (
CreateView,
DeleteView,
Expand Down Expand Up @@ -61,6 +64,7 @@
# ************************
# Ingredient functions
# ************************
@method_decorator(cache_page(settings.WGER_SETTINGS['INGREDIENT_CACHE_TTL']), name='dispatch')
class IngredientListView(ListView):
"""
Show an overview of all ingredients
Expand All @@ -76,9 +80,11 @@ def get_queryset(self):
Filter the ingredients the user will see by its language
"""
language = load_language()
return Ingredient.objects.filter(language=language).only('id', 'name')
return Ingredient.objects.filter(language=language)


# Cache for one week
@cache_page(settings.WGER_SETTINGS['INGREDIENT_CACHE_TTL'])
def view(request, pk, slug=None):
context = {}

Expand Down
1 change: 1 addition & 0 deletions wger/settings_global.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@
'DOWNLOAD_INGREDIENTS_FROM': DOWNLOAD_INGREDIENT_WGER,
'EMAIL_FROM': 'wger Workout Manager <[email protected]>',
'EXERCISE_CACHE_TTL': 3600,
'INGREDIENT_CACHE_TTL': 604800, # one week
'MIN_ACCOUNT_AGE_TO_TRUST': 21,
'SYNC_EXERCISES_CELERY': False,
'SYNC_EXERCISE_IMAGES_CELERY': False,
Expand Down

0 comments on commit e68afe7

Please sign in to comment.