cleaner caching function
This commit is contained in:
@ -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):
|
||||||
|
@ -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'),
|
||||||
|
Reference in New Issue
Block a user