cleaner caching function

This commit is contained in:
vabene1111
2023-02-26 08:49:44 +01:00
parent 1efcf386e2
commit fcf861f5eb
2 changed files with 40 additions and 18 deletions

View File

@ -7,6 +7,7 @@ from html import escape
from smtplib import SMTPException from smtplib import SMTPException
from django.contrib.auth.models import Group, User, AnonymousUser from django.contrib.auth.models import Group, User, AnonymousUser
from django.core.cache import caches
from django.core.mail import send_mail from django.core.mail import send_mail
from django.db.models import Avg, Q, QuerySet, Sum from django.db.models import Avg, Q, QuerySet, Sum
from django.http import BadHeaderError from django.http import BadHeaderError
@ -103,15 +104,17 @@ class CustomOnHandField(serializers.Field):
return instance return instance
def to_representation(self, obj): def to_representation(self, obj):
shared_users = None shared_users = []
if request := self.context.get('request', None): if c := caches['default'].get(f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None):
shared_users = getattr(request, '_shared_users', None) shared_users = c
if shared_users is None: else:
try: try:
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [ shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [
self.context['request'].user.id] self.context['request'].user.id]
caches['default'].set(f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', shared_users, timeout=5*60)
# TODO ugly hack that improves API performance significantly, should be done properly
except AttributeError: # Anonymous users (using share links) don't have shared users except AttributeError: # Anonymous users (using share links) don't have shared users
shared_users = [] pass
return obj.onhand_users.filter(id__in=shared_users).exists() return obj.onhand_users.filter(id__in=shared_users).exists()
def to_internal_value(self, data): def to_internal_value(self, data):
@ -278,11 +281,12 @@ class SpaceSerializer(WritableNestedModelSerializer):
class Meta: class Meta:
model = Space model = Space
fields = ( fields = (
'id', 'name', 'created_by', 'created_at', 'message', 'max_recipes', 'max_file_storage_mb', 'max_users', 'id', 'name', 'created_by', 'created_at', 'message', 'max_recipes', 'max_file_storage_mb', 'max_users',
'allow_sharing', 'demo', 'food_inherit', 'show_facet_count', 'user_count', 'recipe_count', 'file_size_mb', 'allow_sharing', 'demo', 'food_inherit', 'show_facet_count', 'user_count', 'recipe_count', 'file_size_mb',
'image', 'use_plural',) 'image', 'use_plural',)
read_only_fields = ( read_only_fields = (
'id', 'created_by', 'created_at', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing', 'demo',) 'id', 'created_by', 'created_at', 'max_recipes', 'max_file_storage_mb', 'max_users', 'allow_sharing',
'demo',)
class UserSpaceSerializer(WritableNestedModelSerializer): class UserSpaceSerializer(WritableNestedModelSerializer):
@ -531,15 +535,20 @@ class FoodSerializer(UniqueFieldsMixin, WritableNestedModelSerializer, ExtendedR
images = ['recipe__image'] images = ['recipe__image']
def get_substitute_onhand(self, obj): def get_substitute_onhand(self, obj):
shared_users = None shared_users = []
if request := self.context.get('request', None): if c := caches['default'].get(
shared_users = getattr(request, '_shared_users', None) f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None):
if shared_users is None: shared_users = c
else:
try: try:
shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [ shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [
self.context['request'].user.id] self.context['request'].user.id]
except AttributeError: caches['default'].set(
shared_users = [] f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}',
shared_users, timeout=5 * 60)
# TODO ugly hack that improves API performance significantly, should be done properly
except AttributeError: # Anonymous users (using share links) don't have shared users
pass
filter = Q(id__in=obj.substitute.all()) filter = Q(id__in=obj.substitute.all())
if obj.substitute_siblings: if obj.substitute_siblings:
filter |= Q(path__startswith=obj.path[:Food.steplen * (obj.depth - 1)], depth=obj.depth) filter |= Q(path__startswith=obj.path[:Food.steplen * (obj.depth - 1)], depth=obj.depth)
@ -630,7 +639,7 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer):
used_in = [] used_in = []
for s in obj.step_set.all(): for s in obj.step_set.all():
for r in s.recipe_set.all(): for r in s.recipe_set.all():
used_in.append({'id':r.id,'name':r.name}) used_in.append({'id': r.id, 'name': r.name})
return used_in return used_in
def get_conversions(self, obj): def get_conversions(self, obj):

View File

@ -19,6 +19,7 @@ from annoying.functions import get_object_or_None
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.contrib.postgres.search import TrigramSimilarity from django.contrib.postgres.search import TrigramSimilarity
from django.core.cache import caches
from django.core.exceptions import FieldError, ValidationError from django.core.exceptions import FieldError, ValidationError
from django.core.files import File from django.core.files import File
from django.db.models import Case, Count, Exists, OuterRef, ProtectedError, Q, Subquery, Value, When, Avg, Max from django.db.models import Case, Count, Exists, OuterRef, ProtectedError, Q, Subquery, Value, When, Avg, Max
@ -526,8 +527,20 @@ class FoodViewSet(viewsets.ModelViewSet, TreeMixin):
pagination_class = DefaultPagination pagination_class = DefaultPagination
def get_queryset(self): def get_queryset(self):
self.request._shared_users = [x.id for x in list(self.request.user.get_shopping_share())] + [ shared_users = []
self.request.user.id] if c := caches['default'].get(
f'shopping_shared_users_{self.request.space.id}_{self.request.user.id}', None):
shared_users = c
else:
try:
shared_users = [x.id for x in list(self.request.user.get_shopping_share())] + [
self.request.user.id]
caches['default'].set(
f'shopping_shared_users_{self.request.space.id}_{self.request.user.id}',
shared_users, timeout=5 * 60)
# TODO ugly hack that improves API performance significantly, should be done properly
except AttributeError: # Anonymous users (using share links) don't have shared users
pass
self.queryset = super().get_queryset() self.queryset = super().get_queryset()
shopping_status = ShoppingListEntry.objects.filter(space=self.request.space, food=OuterRef('id'), shopping_status = ShoppingListEntry.objects.filter(space=self.request.space, food=OuterRef('id'),