Reduce quota calculations on front page

This commit is contained in:
Raphael Michel
2016-11-08 14:14:10 +01:00
parent 059e6bace5
commit 368d04ae72
2 changed files with 16 additions and 7 deletions

View File

@@ -230,7 +230,7 @@ class Item(LoggedModel):
return False return False
return True return True
def check_quotas(self, ignored_quotas=None): def check_quotas(self, ignored_quotas=None, _cache=None):
""" """
This method is used to determine whether this Item is currently available This method is used to determine whether this Item is currently available
for sale. for sale.
@@ -252,7 +252,7 @@ class Item(LoggedModel):
if self.variations.count() > 0: # NOQA if self.variations.count() > 0: # NOQA
raise ValueError('Do not call this directly on items which have variations ' raise ValueError('Do not call this directly on items which have variations '
'but call this on their ItemVariation objects') 'but call this on their ItemVariation objects')
return min([q.availability() for q in check_quotas], return min([q.availability(_cache=_cache) for q in check_quotas],
key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize)) key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize))
@cached_property @cached_property
@@ -314,7 +314,7 @@ class ItemVariation(models.Model):
if self.item: if self.item:
self.item.event.get_cache().clear() self.item.event.get_cache().clear()
def check_quotas(self, ignored_quotas=None) -> Tuple[int, int]: def check_quotas(self, ignored_quotas=None, _cache=None) -> Tuple[int, int]:
""" """
This method is used to determine whether this ItemVariation is currently This method is used to determine whether this ItemVariation is currently
available for sale in terms of quotas. available for sale in terms of quotas.
@@ -330,7 +330,7 @@ class ItemVariation(models.Model):
check_quotas -= set(ignored_quotas) check_quotas -= set(ignored_quotas)
if not check_quotas: if not check_quotas:
return Quota.AVAILABILITY_OK, sys.maxsize return Quota.AVAILABILITY_OK, sys.maxsize
return min([q.availability() for q in check_quotas], return min([q.availability(_cache=_cache) for q in check_quotas],
key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize)) key=lambda s: (s[0], s[1] if s[1] is not None else sys.maxsize))
def __lt__(self, other): def __lt__(self, other):
@@ -533,7 +533,7 @@ class Quota(LoggedModel):
if self.event: if self.event:
self.event.get_cache().clear() self.event.get_cache().clear()
def availability(self, now_dt: datetime=None) -> Tuple[int, int]: def availability(self, now_dt: datetime=None, _cache=None) -> Tuple[int, int]:
""" """
This method is used to determine whether Items or ItemVariations belonging This method is used to determine whether Items or ItemVariations belonging
to this quota should currently be available for sale. to this quota should currently be available for sale.
@@ -541,6 +541,14 @@ class Quota(LoggedModel):
:returns: a tuple where the first entry is one of the ``Quota.AVAILABILITY_`` constants :returns: a tuple where the first entry is one of the ``Quota.AVAILABILITY_`` constants
and the second is the number of available tickets. and the second is the number of available tickets.
""" """
if _cache is not None and self.pk in _cache:
return _cache[self.pk]
res = self._availability(now_dt)
if _cache is not None:
_cache[self.pk] = res
return res
def _availability(self, now_dt: datetime=None):
now_dt = now_dt or now() now_dt = now_dt or now()
size_left = self.size size_left = self.size
if size_left is None: if size_left is None:

View File

@@ -44,9 +44,10 @@ def get_grouped_items(event):
quotac__gt=0 quotac__gt=0
).order_by('category__position', 'category_id', 'position', 'name') ).order_by('category__position', 'category_id', 'position', 'name')
display_add_to_cart = False display_add_to_cart = False
quota_cache = {}
for item in items: for item in items:
if not item.has_variations: if not item.has_variations:
item.cached_availability = list(item.check_quotas()) item.cached_availability = list(item.check_quotas(_cache=quota_cache))
item.order_max = min(item.cached_availability[1] item.order_max = min(item.cached_availability[1]
if item.cached_availability[1] is not None else sys.maxsize, if item.cached_availability[1] is not None else sys.maxsize,
int(event.settings.max_items_per_order)) int(event.settings.max_items_per_order))
@@ -54,7 +55,7 @@ def get_grouped_items(event):
display_add_to_cart = display_add_to_cart or item.order_max > 0 display_add_to_cart = display_add_to_cart or item.order_max > 0
else: else:
for var in item.available_variations: for var in item.available_variations:
var.cached_availability = list(var.check_quotas()) var.cached_availability = list(var.check_quotas(_cache=quota_cache))
var.order_max = min(var.cached_availability[1] var.order_max = min(var.cached_availability[1]
if var.cached_availability[1] is not None else sys.maxsize, if var.cached_availability[1] is not None else sys.maxsize,
int(event.settings.max_items_per_order)) int(event.settings.max_items_per_order))