简体   繁体   English

Django transaction.atomic() 不起作用

[英]Django transaction.atomic() does not work

I have a problem with this code:我对这段代码有问题:

PhoneNumberFormSet = inlineformset_factory(Person, PhoneNumber, fields=('phone_number',), 
can_delete=False, extra=1)

EmailAddressFormSet = inlineformset_factory(Person, EmailAddress, fields=('email_address',), 
can_delete=False, extra=1)

class PersonCreateView(CreateView):

    form_class = PersonForm
    success_url = reverse_lazy('person-list')
    template_name = 'contacts/person_create.html'

    def get_context_data(self, **kwargs):
        data = super(PersonCreateView, self).get_context_data(**kwargs)
        data['phone_formset'] = PhoneNumberFormSet(self.request.POST or None)
        data['email_formset'] = EmailAddressFormSet(self.request.POST or None)
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        phone_formset = context['phone_formset']
        email_formset = context['email_formset']
        with transaction.atomic():
            o = form.save() # <--- this object is saved even when formsets below are not valid
            condition = phone_formset.is_valid() and email_formset.is_valid()
            if not condition:
                return render(self.request, self.template_name, self.get_context_data())
            phone_formset.instance = o
            phone_formset.save()
            email_formset.instance = o
            email_formset.save()
        return super(PersonCreateView, self).form_valid(form)

The transaction.atomic() is saving obcject "o" even when phone_formset or email_formset are not valid and view renders forms with errors (object should not be saved)即使 phone_formset 或 email_formset 无效并且视图呈现带有错误的表单(不应保存对象),transaction.atomic() 也会保存对象“o”

It doesn't work because atomic transactions roll back only if exception is raised.它不起作用,因为原子事务只有在引发异常时才会回滚。 In your case, you just return normal response object, which doesn't trigger roll back and hence commits to database.在您的情况下,您只返回正常的响应对象,它不会触发回滚并因此提交到数据库。

More about atomic transactions in django docs .更多关于Django 文档中的原子事务。

Change your code to something like this (didn't confirm it's working, but this type of example is in the linked docs):将您的代码更改为这样的内容(未确认它是否正常工作,但此类示例在链接的文档中):

from django.core.exceptions import ValidationError

def form_valid(self, form):
        context = self.get_context_data()
        phone_formset = context['phone_formset']
        email_formset = context['email_formset']
        try:
            with transaction.atomic():
                o = form.save() # <--- this object is saved even when formsets below are not valid
                condition = phone_formset.is_valid() and email_formset.is_valid()
                if not condition:
                    raise ValidationError
                phone_formset.instance = o
                phone_formset.save()
                email_formset.instance = o
                email_formset.save()
        except ValidationError:
            return render(self.request, self.template_name, self.get_context_data())
        return super(PersonCreateView, self).form_valid(form)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM