Do not use deepcopy on models

This commit is contained in:
Raphael Michel
2018-08-07 15:43:57 +02:00
parent 0c0172a0b6
commit c702814203
7 changed files with 31 additions and 13 deletions

View File

@@ -1,4 +1,3 @@
import copy
import json import json
import logging import logging
import urllib.error import urllib.error
@@ -27,6 +26,7 @@ from pretix.base.settings import GlobalSettingsObject
from pretix.base.signals import periodic_task from pretix.base.signals import periodic_task
from pretix.celery_app import app from pretix.celery_app import app
from pretix.helpers.database import rolledback_transaction from pretix.helpers.database import rolledback_transaction
from pretix.helpers.models import modelcopy
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -171,7 +171,7 @@ def build_cancellation(invoice: Invoice):
def generate_cancellation(invoice: Invoice, trigger_pdf=True): def generate_cancellation(invoice: Invoice, trigger_pdf=True):
cancellation = copy.deepcopy(invoice) cancellation = modelcopy(invoice)
cancellation.pk = None cancellation.pk = None
cancellation.invoice_no = None cancellation.invoice_no = None
cancellation.prefix = None cancellation.prefix = None

View File

@@ -1,4 +1,3 @@
import copy
import json import json
import logging import logging
from collections import Counter, namedtuple from collections import Counter, namedtuple
@@ -44,6 +43,7 @@ from pretix.base.signals import (
allow_ticket_download, order_fee_calculation, order_placed, periodic_task, allow_ticket_download, order_fee_calculation, order_placed, periodic_task,
) )
from pretix.celery_app import app from pretix.celery_app import app
from pretix.helpers.models import modelcopy
from pretix.multidomain.urlreverse import build_absolute_uri from pretix.multidomain.urlreverse import build_absolute_uri
error_messages = { error_messages = {
@@ -923,7 +923,7 @@ class OrderChangeManager:
op.save() op.save()
try: try:
ia = copy.deepcopy(self.order.invoice_address) ia = modelcopy(self.order.invoice_address)
ia.pk = None ia.pk = None
ia.order = split_order ia.order = split_order
ia.save() ia.save()
@@ -947,7 +947,7 @@ class OrderChangeManager:
split_order.total += fee.value split_order.total += fee.value
for fee in self.order.fees.exclude(fee_type=OrderFee.FEE_TYPE_PAYMENT): for fee in self.order.fees.exclude(fee_type=OrderFee.FEE_TYPE_PAYMENT):
new_fee = copy.deepcopy(fee) new_fee = modelcopy(fee)
new_fee.pk = None new_fee.pk = None
new_fee.order = split_order new_fee.order = split_order
split_order.total += new_fee.value split_order.total += new_fee.value

View File

@@ -1,5 +1,3 @@
import copy
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.models import Max from django.db.models import Max
@@ -18,6 +16,7 @@ from pretix.base.models.items import ItemAddOn
from pretix.base.signals import item_copy_data from pretix.base.signals import item_copy_data
from pretix.control.forms import SplitDateTimePickerWidget from pretix.control.forms import SplitDateTimePickerWidget
from pretix.control.forms.widgets import Select2 from pretix.control.forms.widgets import Select2
from pretix.helpers.models import modelcopy
from pretix.helpers.money import change_decimal_field from pretix.helpers.money import change_decimal_field
@@ -78,7 +77,7 @@ class QuotaForm(I18nModelForm):
self.instance = kwargs.get('instance', None) self.instance = kwargs.get('instance', None)
self.event = kwargs.get('event') self.event = kwargs.get('event')
items = kwargs.pop('items', None) or self.event.items.prefetch_related('variations') items = kwargs.pop('items', None) or self.event.items.prefetch_related('variations')
self.original_instance = copy.deepcopy(self.instance) if self.instance else None self.original_instance = modelcopy(self.instance) if self.instance else None
initial = kwargs.get('initial', {}) initial = kwargs.get('initial', {})
if self.instance and self.instance.pk: if self.instance and self.instance.pk:
initial['itemvars'] = [str(i.pk) for i in self.instance.items.all()] + [ initial['itemvars'] = [str(i.pk) for i in self.instance.items.all()] + [

View File

@@ -1,5 +1,3 @@
import copy
from django import forms from django import forms
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.models.functions import Lower from django.db.models.functions import Lower
@@ -11,6 +9,7 @@ from pretix.base.models import Item, Voucher
from pretix.control.forms import SplitDateTimePickerWidget from pretix.control.forms import SplitDateTimePickerWidget
from pretix.control.forms.widgets import Select2, Select2ItemVarQuota from pretix.control.forms.widgets import Select2, Select2ItemVarQuota
from pretix.control.signals import voucher_form_validation from pretix.control.signals import voucher_form_validation
from pretix.helpers.models import modelcopy
class FakeChoiceField(forms.ChoiceField): class FakeChoiceField(forms.ChoiceField):
@@ -45,7 +44,7 @@ class VoucherForm(I18nModelForm):
instance = kwargs.get('instance') instance = kwargs.get('instance')
initial = kwargs.get('initial') initial = kwargs.get('initial')
if instance: if instance:
self.initial_instance_data = copy.deepcopy(instance) self.initial_instance_data = modelcopy(instance)
try: try:
if instance.variation: if instance.variation:
initial['itemvar'] = '%d-%d' % (instance.item.pk, instance.variation.pk) initial['itemvar'] = '%d-%d' % (instance.item.pk, instance.variation.pk)
@@ -217,7 +216,7 @@ class VoucherBulkForm(VoucherForm):
def save(self, event, *args, **kwargs): def save(self, event, *args, **kwargs):
objs = [] objs = []
for code in self.cleaned_data['codes']: for code in self.cleaned_data['codes']:
obj = copy.deepcopy(self.instance) obj = modelcopy(self.instance)
obj.event = event obj.event = event
obj.code = code obj.code = code
data = dict(self.cleaned_data) data = dict(self.cleaned_data)

View File

@@ -33,6 +33,7 @@ from pretix.control.forms.subevents import (
from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.permissions import EventPermissionRequiredMixin
from pretix.control.views import PaginationMixin from pretix.control.views import PaginationMixin
from pretix.control.views.event import MetaDataEditorMixin from pretix.control.views.event import MetaDataEditorMixin
from pretix.helpers.models import modelcopy
class SubEventList(EventPermissionRequiredMixin, PaginationMixin, ListView): class SubEventList(EventPermissionRequiredMixin, PaginationMixin, ListView):
@@ -424,7 +425,7 @@ class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateVi
kwargs = super().get_form_kwargs() kwargs = super().get_form_kwargs()
kwargs['event'] = self.request.event kwargs['event'] = self.request.event
if self.copy_from: if self.copy_from:
i = copy.deepcopy(self.copy_from) i = modelcopy(self.copy_from)
i.pk = None i.pk = None
kwargs['instance'] = i kwargs['instance'] = i
else: else:

View File

@@ -1,3 +1,5 @@
import copy
from django.db import models from django.db import models
@@ -8,3 +10,14 @@ class Thumbnail(models.Model):
class Meta: class Meta:
unique_together = (('source', 'size'),) unique_together = (('source', 'size'),)
def modelcopy(obj: models.Model):
n = copy.copy(obj)
for f in obj._meta.fields:
val = getattr(obj, f.name)
if isinstance(val, models.Model):
setattr(n, f.name, val)
else:
setattr(n, f.name, copy.deepcopy(val))
return n

View File

@@ -394,6 +394,12 @@ class VoucherFormTest(SoupTest):
'itemvar': '%d' % self.shirt.pk, 'itemvar': '%d' % self.shirt.pk,
}) })
def test_create_bulk_many(self):
self._create_bulk_vouchers({
'codes': 'ABCDE\nDEFGH\nIJKLM\nNOPQR\nSTUVW\nXYZ',
'itemvar': '%d' % self.ticket.pk,
})
def test_create_blocking_bulk_quota_full(self): def test_create_blocking_bulk_quota_full(self):
self.quota_tickets.size = 0 self.quota_tickets.size = 0
self.quota_tickets.save() self.quota_tickets.save()