mirror of
https://github.com/pretix/pretix.git
synced 2026-05-13 16:33:59 +00:00
Add a custom context manager for rollbacks (#282)
This commit is contained in:
@@ -26,6 +26,7 @@ from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order
|
||||
from pretix.base.services.async import TransactionAwareTask
|
||||
from pretix.base.signals import register_payment_providers
|
||||
from pretix.celery import app
|
||||
from pretix.helpers.database import rolledback_transaction
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
@@ -408,12 +409,10 @@ class DummyRollbackException(Exception):
|
||||
|
||||
def build_preview_invoice_pdf(event):
|
||||
locale = event.settings.invoice_language
|
||||
pdf = None
|
||||
if not locale or locale == '__user__':
|
||||
locale = event.settings.locale
|
||||
|
||||
try:
|
||||
with transaction.atomic(), language(locale):
|
||||
with rolledback_transaction(), language(locale):
|
||||
order = event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
|
||||
expires=now(), code="PREVIEW", total=119)
|
||||
invoice = Invoice(
|
||||
@@ -444,9 +443,4 @@ def build_preview_invoice_pdf(event):
|
||||
with tempfile.NamedTemporaryFile(suffix=".pdf") as f:
|
||||
_invoice_generate_german(invoice, f)
|
||||
f.seek(0)
|
||||
pdf = f.read()
|
||||
raise DummyRollbackException()
|
||||
except DummyRollbackException:
|
||||
return pdf
|
||||
else:
|
||||
raise Exception('Invalid state, should have rolled back.')
|
||||
return f.read()
|
||||
|
||||
@@ -11,6 +11,7 @@ from pretix.base.models import (
|
||||
)
|
||||
from pretix.base.signals import register_ticket_outputs
|
||||
from pretix.celery import app
|
||||
from pretix.helpers.database import rolledback_transaction
|
||||
|
||||
|
||||
@app.task
|
||||
@@ -41,10 +42,8 @@ class DummyRollbackException(Exception):
|
||||
|
||||
def preview(event: int, provider: str):
|
||||
event = Event.objects.get(id=event)
|
||||
res = None
|
||||
|
||||
try:
|
||||
with transaction.atomic(), language(event.settings.locale):
|
||||
with rolledback_transaction(), language(event.settings.locale):
|
||||
item = event.items.create(name=_("Sample product"), default_price=42.23)
|
||||
|
||||
order = event.orders.create(status=Order.STATUS_PENDING, datetime=now(),
|
||||
@@ -56,9 +55,4 @@ def preview(event: int, provider: str):
|
||||
for receiver, response in responses:
|
||||
prov = response(event)
|
||||
if prov.identifier == provider:
|
||||
res = prov.generate(order)
|
||||
raise DummyRollbackException()
|
||||
except DummyRollbackException:
|
||||
return res
|
||||
else:
|
||||
raise Exception('Invalid state, should have rolled back.')
|
||||
return prov.generate(order)
|
||||
|
||||
28
src/pretix/helpers/database.py
Normal file
28
src/pretix/helpers/database.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import contextlib
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
|
||||
class DummyRollbackException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def rolledback_transaction():
|
||||
"""
|
||||
This context manager runs your code in a database transaction that will be rolled back in the end.
|
||||
This can come in handy to simulate the effects of a database operation that you do not actually
|
||||
want to perform.
|
||||
|
||||
Note that rollbacks are a very slow operation on most database backends. Also, long-running
|
||||
transactions can slow down other operations currently running and you should not use this
|
||||
in a place that is called frequently.
|
||||
"""
|
||||
try:
|
||||
with transaction.atomic():
|
||||
yield
|
||||
raise DummyRollbackException()
|
||||
except DummyRollbackException:
|
||||
pass
|
||||
else:
|
||||
raise Exception('Invalid state, should have rolled back.')
|
||||
Reference in New Issue
Block a user