Django-使用事务atomi回滚保存

2024-05-08 23:55:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一个保存对象的视图,但如果出现异常,我想撤消保存的视图。我就是这么想的:

class MyView(View):

    @transation.atomic
    def post(self, request, *args, **kwargs):
        try:
            some_object = SomeModel(...)
            some_object.save()

            if something:
                raise exception.NotAcceptable()
                # When the workflow comes into this condition, I think the previous save should be undome
                # Whant am I missing?

        except exception.NotAcceptable, e:
            # do something

我做错什么了?即使引发异常,some_object仍在数据库中。


Tags: python
3条回答

Atomicity Documentation

总而言之,@transaction.atomic将在数据库上执行一个事务,如果您的视图生成一个没有错误的响应。因为您自己正在捕捉异常,所以在Django看来,您的视图执行得很好。

如果捕捉到异常,则需要自己处理:Controlling Transactions

如果在失败时需要生成正确的json响应:

from django.db import SomeError, transaction

def viewfunc(request):
    do_something()

    try:
        with transaction.atomic():
            thing_that_might_fail()
    except SomeError:
        handle_exception()

    render_response()

对我来说这在Django 2.2.5工作

首先在你的设置中.py

...

DATABASES = {
    'default': {
        'ENGINE': 'xxx',  # transactional db
        ...
        'ATOMIC_REQUESTS': True,
    }
}

在你的函数中(views.py)

from django.db import transaction

@transaction.atomic
def make_db_stuff():

    # do stuff in your db (inserts or whatever)

    if success:
        return True
    else:
        transaction.set_rollback(True)
        return False

但是,如果在用transaction.atomic修饰的函数中发生异常,则无需执行任何操作,它将rollback automatically to the savepoint created by the decorator before running the your function,如documented

atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.

如果异常在except块中捕获,则应重新引发该异常,以便atomic捕获该异常并执行回滚,即:

    try:
        some_object = SomeModel(...)
        some_object.save()

        if something:
            raise exception.NotAcceptable()
            # When the workflow comes into this condition, I think the previous save should be undome
            # Whant am I missing?

    except exception.NotAcceptable, e:
        # do something
        raise  # re-raise the exception to make transaction.atomic rollback

另外,如果需要更多控制,可以手动回滚到previously set savepoint,即:

class MyView(View):
    def post(self, request, *args, **kwargs):
        sid = transaction.savepoint()
        some_object = SomeModel(...)
        some_object.save()

        if something:
            transaction.savepoint_rollback(sid)
        else:
            try:
                # In worst case scenario, this might fail too
                transaction.savepoint_commit(sid)
            except IntegrityError:
                transaction.savepoint_rollback(sid)

相关问题 更多 >

    热门问题