forked from CGM_Public/pretix_original
Reduce number of redundant SQL queries
This commit is contained in:
@@ -15,33 +15,24 @@ class CartMixin:
|
||||
"""
|
||||
A list of this users cart position
|
||||
"""
|
||||
return list(CartPosition.objects.filter(
|
||||
cart_id=self.request.session.session_key, event=self.request.event
|
||||
).order_by(
|
||||
'item', 'variation'
|
||||
).select_related(
|
||||
'item', 'variation'
|
||||
).prefetch_related(
|
||||
'item__questions', 'answers'
|
||||
))
|
||||
return list(get_cart(self.request))
|
||||
|
||||
def get_cart(self, answers=False, queryset=None, payment_fee=None, payment_fee_tax_rate=None, downloads=False):
|
||||
queryset = queryset or CartPosition.objects.filter(
|
||||
cart_id=self.request.session.session_key, event=self.request.event
|
||||
)
|
||||
if queryset:
|
||||
prefetch = []
|
||||
if answers:
|
||||
prefetch.append('item__questions')
|
||||
prefetch.append('answers')
|
||||
|
||||
prefetch = []
|
||||
if answers:
|
||||
prefetch.append('item__questions')
|
||||
prefetch.append('answers')
|
||||
|
||||
cartpos = queryset.order_by(
|
||||
'item', 'variation'
|
||||
).select_related(
|
||||
'item', 'variation'
|
||||
).prefetch_related(
|
||||
*prefetch
|
||||
)
|
||||
cartpos = queryset.order_by(
|
||||
'item', 'variation'
|
||||
).select_related(
|
||||
'item', 'variation'
|
||||
).prefetch_related(
|
||||
*prefetch
|
||||
)
|
||||
else:
|
||||
cartpos = self.positions
|
||||
|
||||
# Group items of the same variation
|
||||
# We do this by list manipulations instead of a GROUP BY query, as
|
||||
@@ -101,6 +92,20 @@ class CartMixin:
|
||||
return payment_fee
|
||||
|
||||
|
||||
def get_cart(request):
|
||||
if not hasattr(request, '_cart_cache'):
|
||||
request._cart_cache = CartPosition.objects.filter(
|
||||
cart_id=request.session.session_key, event=request.event
|
||||
).order_by(
|
||||
'item', 'variation'
|
||||
).select_related(
|
||||
'item', 'variation'
|
||||
).prefetch_related(
|
||||
'item__questions', 'answers'
|
||||
)
|
||||
return request._cart_cache
|
||||
|
||||
|
||||
class EventViewMixin:
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
@@ -4,15 +4,17 @@ from django.shortcuts import redirect
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import View
|
||||
|
||||
from pretix.base.models import CartPosition
|
||||
from pretix.multidomain.urlreverse import eventreverse
|
||||
from pretix.presale.checkoutflow import get_checkout_flow
|
||||
from pretix.presale.views import CartMixin
|
||||
|
||||
|
||||
class CheckoutView(CartMixin, View):
|
||||
class CheckoutView(View):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
if not self.positions and "async_id" not in request.GET:
|
||||
has_cart = CartPosition.objects.filter(
|
||||
cart_id=self.request.session.session_key, event=self.request.event).exists()
|
||||
if not has_cart and "async_id" not in request.GET:
|
||||
messages.error(request, _("Your cart is empty"))
|
||||
return redirect(eventreverse(self.request.event, 'presale:event.index'))
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import sys
|
||||
|
||||
from django.db.models import Count, Q
|
||||
from django.db.models import Count, Prefetch, Q
|
||||
from django.utils.timezone import now
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from pretix.base.models import ItemVariation
|
||||
|
||||
from . import CartMixin, EventViewMixin
|
||||
|
||||
|
||||
@@ -21,48 +23,56 @@ def item_group_by_category(items):
|
||||
)
|
||||
|
||||
|
||||
def get_grouped_items(event):
|
||||
items = event.items.all().filter(
|
||||
Q(active=True)
|
||||
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
|
||||
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
|
||||
& Q(hide_without_voucher=False)
|
||||
).select_related(
|
||||
'category', # for re-grouping
|
||||
).prefetch_related(
|
||||
'quotas', 'variations__quotas', 'quotas__event', # for .availability()
|
||||
Prefetch('variations', to_attr='available_variations',
|
||||
queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).distinct()),
|
||||
).annotate(
|
||||
quotac=Count('quotas'),
|
||||
has_variations=Count('variations')
|
||||
).filter(
|
||||
quotac__gt=0
|
||||
).order_by('category__position', 'category_id', 'position', 'name')
|
||||
display_add_to_cart = False
|
||||
for item in items:
|
||||
if not item.has_variations:
|
||||
item.cached_availability = list(item.check_quotas())
|
||||
item.order_max = min(item.cached_availability[1]
|
||||
if item.cached_availability[1] is not None else sys.maxsize,
|
||||
int(event.settings.max_items_per_order))
|
||||
item.price = item.default_price
|
||||
display_add_to_cart = display_add_to_cart or item.order_max > 0
|
||||
else:
|
||||
for var in item.available_variations:
|
||||
var.cached_availability = list(var.check_quotas())
|
||||
var.order_max = min(var.cached_availability[1]
|
||||
if var.cached_availability[1] is not None else sys.maxsize,
|
||||
int(event.settings.max_items_per_order))
|
||||
display_add_to_cart = display_add_to_cart or var.order_max > 0
|
||||
var.price = var.default_price if var.default_price is not None else item.default_price
|
||||
if len(item.available_variations) > 0:
|
||||
item.min_price = min([v.price for v in item.available_variations])
|
||||
item.max_price = max([v.price for v in item.available_variations])
|
||||
|
||||
items = [item for item in items if len(item.available_variations) > 0 or not item.has_variations]
|
||||
return items, display_add_to_cart
|
||||
|
||||
|
||||
class EventIndex(EventViewMixin, CartMixin, TemplateView):
|
||||
template_name = "pretixpresale/event/index.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
# Fetch all items
|
||||
items = self.request.event.items.all().filter(
|
||||
Q(active=True)
|
||||
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
|
||||
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
|
||||
& Q(hide_without_voucher=False)
|
||||
).select_related(
|
||||
'category', # for re-grouping
|
||||
).prefetch_related(
|
||||
'quotas', 'variations__quotas', 'quotas__event' # for .availability()
|
||||
).annotate(quotac=Count('quotas')).filter(
|
||||
quotac__gt=0
|
||||
).order_by('category__position', 'category_id', 'position', 'name')
|
||||
display_add_to_cart = False
|
||||
for item in items:
|
||||
item.available_variations = list(item.variations.filter(active=True, quotas__isnull=False).distinct())
|
||||
item.has_variations = item.variations.exists()
|
||||
if not item.has_variations:
|
||||
item.cached_availability = list(item.check_quotas())
|
||||
item.order_max = min(item.cached_availability[1]
|
||||
if item.cached_availability[1] is not None else sys.maxsize,
|
||||
int(self.request.event.settings.max_items_per_order))
|
||||
item.price = item.default_price
|
||||
display_add_to_cart = display_add_to_cart or item.order_max > 0
|
||||
else:
|
||||
for var in item.available_variations:
|
||||
var.cached_availability = list(var.check_quotas())
|
||||
var.order_max = min(var.cached_availability[1]
|
||||
if var.cached_availability[1] is not None else sys.maxsize,
|
||||
int(self.request.event.settings.max_items_per_order))
|
||||
display_add_to_cart = display_add_to_cart or var.order_max > 0
|
||||
var.price = var.default_price if var.default_price is not None else item.default_price
|
||||
if len(item.available_variations) > 0:
|
||||
item.min_price = min([v.price for v in item.available_variations])
|
||||
item.max_price = max([v.price for v in item.available_variations])
|
||||
|
||||
items = [item for item in items if len(item.available_variations) > 0 or not item.has_variations]
|
||||
items, display_add_to_cart = get_grouped_items(self.request.event)
|
||||
|
||||
# Regroup those by category
|
||||
context['items_by_category'] = item_group_by_category(items)
|
||||
|
||||
@@ -34,7 +34,7 @@ class OrderDetailMixin:
|
||||
@cached_property
|
||||
def order(self):
|
||||
try:
|
||||
order = Order.objects.get(event=self.request.event, code=self.kwargs['order'])
|
||||
order = self.request.event.orders.get(code=self.kwargs['order'])
|
||||
if order.secret.lower() == self.kwargs['secret'].lower():
|
||||
return order
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user