繁体   English   中英

Django - 使用事务原子回滚保存

[英]Django - Rollback save with transaction atomic

我正在尝试创建一个保存对象的视图,但如果出现某些异常,我想撤消该保存。 这是我试过的:

class MyView(View):

    @transaction.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 undone
                # What am I missing?

        except exception.NotAcceptable, e:
            # do something

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

原子性文档

总而言之,如果您的视图产生无错误的响应, @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()

但是,如果在用 transaction.atomic 装饰的函数中发生异常,那么您无需执行任何操作,它会自动回滚到装饰器在运行您的函数之前创建的保存点,如文档所示

atomic 允许我们创建一个代码块,其中保证了数据库的原子性。 如果代码块成功完成,更改将提交到数据库。 如果出现异常,则回滚更改。

如果异常在 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

另外,如果你想要更多的控制,你可以手动回滚到以前设置的保存点,即:

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)

对我来说,这适用于 Django 2.2.5

首先在你的 settings.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

暂无
暂无

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

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