Isolate cart sessions

This commit is contained in:
Raphael Michel
2017-09-10 20:34:21 +02:00
parent f15a72e59d
commit 26f258c6cf
10 changed files with 126 additions and 50 deletions

View File

@@ -19,6 +19,11 @@ class CartMixin:
"""
return list(get_cart(self.request))
@cached_property
def cart_session(self):
from pretix.presale.views.cart import cart_session
return cart_session(self.request)
def get_cart(self, answers=False, queryset=None, order=None, downloads=False):
if queryset:
prefetch = []
@@ -102,7 +107,7 @@ class CartMixin:
if order:
fees = order.fees.all()
else:
iapk = self.request.session.get('invoice_address_{}'.format(self.request.event.pk))
iapk = self.cart_session.get('invoice_address')
ia = None
if iapk:
try:
@@ -110,7 +115,7 @@ class CartMixin:
except InvoiceAddress.DoesNotExist:
pass
fees = get_fees(self.request.event, self.request, total, ia, self.request.session.get('payment'))
fees = get_fees(self.request.event, self.request, total, ia, self.cart_session.get('payment'))
total += sum([f.value for f in fees])
net_total += sum([f.net_value for f in fees])
@@ -137,9 +142,11 @@ class CartMixin:
def get_cart(request):
from pretix.presale.views.cart import get_or_create_cart_id
if not hasattr(request, '_cart_cache'):
request._cart_cache = CartPosition.objects.filter(
cart_id=request.session.session_key, event=request.event
cart_id=get_or_create_cart_id(request), event=request.event
).order_by(
'item', 'variation'
).select_related(
@@ -152,12 +159,14 @@ def get_cart(request):
def get_cart_total(request):
from pretix.presale.views.cart import get_or_create_cart_id
if not hasattr(request, '_cart_total_cache'):
if hasattr(request, '_cart_cache'):
request._cart_total_cache = sum(i.price for i in request._cart_cache)
else:
request._cart_total_cache = CartPosition.objects.filter(
cart_id=request.session.session_key, event=request.event
cart_id=get_or_create_cart_id(request), event=request.event
).aggregate(sum=Sum('price'))['sum'] or 0
return request._cart_total_cache

View File

@@ -6,6 +6,7 @@ from django.db.models import Count, Prefetch, Q
from django.http import FileResponse, Http404, JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.utils import translation
from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.timezone import now
from django.utils.translation import ugettext as _
@@ -39,9 +40,13 @@ class CartActionMixin:
def get_error_url(self):
return self.get_next_url()
@cached_property
def cart_session(self):
return cart_session(self.request)
@cached_property
def invoice_address(self):
iapk = self.request.session.get('invoice_address_{}'.format(self.request.event.pk))
iapk = self.cart_session.get('invoice_address')
if not iapk:
return InvoiceAddress()
@@ -124,19 +129,49 @@ class CartActionMixin:
return items
def create_empty_cart_id(request):
current_id = request.session.get('current_cart_event_{}'.format(request.event.pk))
if current_id and current_id in request.session.get('carts', {}):
del request.session['carts'][current_id]
del request.session['current_cart_event_{}'.format(request.event.pk)]
return get_or_create_cart_id(request)
def get_or_create_cart_id(request):
current_id = request.session.get('current_cart_event_{}'.format(request.event.pk))
if current_id and current_id in request.session.get('carts', {}):
return current_id
else:
while True:
new_id = get_random_string(length=32)
if not CartPosition.objects.filter(cart_id=new_id).exists():
break
if 'carts' not in request.session:
request.session['carts'] = {}
request.session['carts'][new_id] = {}
request.session['current_cart_event_{}'.format(request.event.pk)] = new_id
return new_id
def cart_session(request):
request.session.modified = True
return request.session['carts'][get_or_create_cart_id(request)]
class CartRemove(EventViewMixin, CartActionMixin, AsyncAction, View):
task = remove_cart_position
known_errortypes = ['CartError']
def get_success_message(self, value):
if CartPosition.objects.filter(cart_id=self.request.session.session_key).exists():
if CartPosition.objects.filter(cart_id=get_or_create_cart_id(self.request)).exists():
return _('Your cart has been updated.')
else:
return _('Your cart is now empty.')
def post(self, request, *args, **kwargs):
if 'id' in request.POST:
return self.do(self.request.event.id, request.POST.get('id'), self.request.session.session_key, translation.get_language())
return self.do(self.request.event.id, request.POST.get('id'), get_or_create_cart_id(self.request), translation.get_language())
else:
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
return JsonResponse({
@@ -154,7 +189,7 @@ class CartClear(EventViewMixin, CartActionMixin, AsyncAction, View):
return _('Your cart is now empty.')
def post(self, request, *args, **kwargs):
return self.do(self.request.event.id, self.request.session.session_key, translation.get_language())
return self.do(self.request.event.id, get_or_create_cart_id(self.request), translation.get_language())
class CartAdd(EventViewMixin, CartActionMixin, AsyncAction, View):
@@ -167,7 +202,7 @@ class CartAdd(EventViewMixin, CartActionMixin, AsyncAction, View):
def post(self, request, *args, **kwargs):
items = self._items_from_post_data()
if items:
return self.do(self.request.event.id, items, self.request.session.session_key, translation.get_language(),
return self.do(self.request.event.id, items, get_or_create_cart_id(self.request), translation.get_language(),
self.invoice_address.pk)
else:
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
@@ -299,7 +334,7 @@ class RedeemView(NoSearchIndexViewMixin, EventViewMixin, TemplateView):
redeemed_in_carts = CartPosition.objects.filter(
Q(voucher=self.voucher) & Q(event=request.event) &
(Q(expires__gte=now()) | Q(cart_id=request.session.session_key))
(Q(expires__gte=now()) | Q(cart_id=get_or_create_cart_id(request)))
)
v_avail = self.voucher.max_usages - self.voucher.redeemed - redeemed_in_carts.count()
if v_avail < 1:
@@ -337,7 +372,7 @@ class AnswerDownload(EventViewMixin, View):
answid = kwargs.get('answer')
answer = get_object_or_404(
QuestionAnswer,
cartposition__cart_id=self.request.session.session_key,
cartposition__cart_id=get_or_create_cart_id(self.request),
id=answid
)
if not answer.file:

View File

@@ -9,13 +9,15 @@ from pretix.base.services.cart import CartError
from pretix.base.signals import validate_cart
from pretix.multidomain.urlreverse import eventreverse
from pretix.presale.checkoutflow import get_checkout_flow
from pretix.presale.views.cart import get_or_create_cart_id
class CheckoutView(View):
def dispatch(self, request, *args, **kwargs):
self.request = request
cart_pos = CartPosition.objects.filter(
cart_id=self.request.session.session_key, event=self.request.event
cart_id=get_or_create_cart_id(request), event=self.request.event
)
if not cart_pos.exists() and "async_id" not in request.GET: