Optimize availability queries

This commit is contained in:
Raphael Michel
2024-07-02 18:29:44 +02:00
parent 94d13e4cdd
commit a173e347ea
7 changed files with 109 additions and 75 deletions

View File

@@ -304,10 +304,13 @@ class EventMixin:
return safe_string(json.dumps(eventdict))
@classmethod
def annotated(cls, qs, channel='web', voucher=None):
from pretix.base.models import Item, ItemVariation, Quota
def annotated(cls, qs, channel, voucher=None):
# Channel can currently be a SalesChannel or a str, since we need that compatibility, but a SalesChannel
# makes the query SIGNIFICANTLY faster
from pretix.base.models import Item, ItemVariation, Quota, SalesChannel
assert isinstance(channel, (SalesChannel, str))
assert isinstance(channel, str)
sq_active_item = Item.objects.using(settings.DATABASE_REPLICA).filter_available(channel=channel, voucher=voucher).filter(
Q(variations__isnull=True)
& Q(quotas__pk=OuterRef('pk'))
@@ -317,18 +320,23 @@ class EventMixin:
q_variation = (
Q(active=True)
& Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
& Q(Q(available_from__isnull=True) | Q(available_from__lte=time_machine_now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=time_machine_now()))
& Q(item__active=True)
& Q(Q(item__available_from__isnull=True) | Q(item__available_from__lte=time_machine_now()))
& Q(Q(item__available_until__isnull=True) | Q(item__available_until__gte=time_machine_now()))
& Q(Q(item__category__isnull=True) | Q(item__category__is_addon=False))
& Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__identifier=channel))
& Q(item__require_bundling=False)
& Q(quotas__pk=OuterRef('pk'))
)
if isinstance(channel, str):
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels__identifier=channel))
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels__identifier=channel))
else:
q_variation &= Q(Q(all_sales_channels=True) | Q(limit_sales_channels=channel))
q_variation &= Q(Q(item__all_sales_channels=True) | Q(item__limit_sales_channels=channel))
if voucher:
if voucher.variation_id:
q_variation &= Q(pk=voucher.variation_id)
@@ -1536,8 +1544,11 @@ class SubEvent(EventMixin, LoggedModel):
return qs_annotated
@classmethod
def annotated(cls, qs, channel='web', voucher=None):
def annotated(cls, qs, channel, voucher=None):
from .items import SubEventItem, SubEventItemVariation
from .organizer import SalesChannel
assert isinstance(channel, (str, SalesChannel))
qs = super().annotated(qs, channel, voucher=voucher)
qs = qs.annotate(