【问题标题】:How to use django TransactionMiddleware with MySQL database如何在 MySQL 数据库中使用 django 事务中间件
【发布时间】:2023-04-07 12:25:01
【问题描述】:

在我正在进行的一个项目中,我明确地使用如下事务:

from django.db import transaction

@transaction.commit_on_succcess
def some_view(request):
    """ Renders some view
    """

我正在使用 Django 1.5.5,在文档中它说:

在 Web 请求中处理事务的推荐方法是通过 Django 的 TransactionMiddleware 将它们绑定到请求和响应阶段。

它是这样工作的:当一个请求开始时,Django 开始一个事务。如果生成的响应没有问题,Django 将提交任何未决事务。如果视图函数产生异常,Django 会回滚所有待处理的事务。

要激活此功能,只需将 TransactionMiddleware 中间件添加到您的 MIDDLEWARE_CLASSES 设置:

我想在请求中使用事务,而不是将它们绑定到需要它的特定视图,但我对它的工作原理有点困惑。假设我的观点如下:

def some_view(request):
    """ Creates a user object.
    """

    context = {}
    first_name = request.POST['first_name']
    last_name = request.POST['last_name']
    email = request.POST['email']

    try:
        create_user(first_name, last_name, email)
        context['success'] = 'User %s was added to the database.' % (first_name)
    except IntegrityError, err:
        context['failure'] = 'An error occurred while adding user to the database: %s' % (str(err))
    except Exception, err:
        context['failure'] = '%s' % (str(err))

   return json_response(context)

在上面的视图中,我们正在处理异常并返回响应,并在文档中声明:

如果生成的响应没有问题,Django 会提交任何未决事务。

:即使引发异常,事务是否会在上述视图中提交?

如果我们想在一个请求中创建多个对象,并且只想回滚一个引发异常但提交所有其他的条目怎么办?因此,例如,我们从文件中读取数据,并且对于要创建用户对象的每一行,我们希望将所有用户插入到数据库中,但引发错误的用户除外:

def some_view(request):
    """ Creates a user object.
    """

    context = {}
    data = # Read from file

    for row in data:
        first_name, last_name, email = row.split(",")

        try:
            create_user(first_name, last_name, email)
            context['success'] = 'User %s was added to the database.' % (first_name)
        except IntegrityError, err:
            context['failure'] = 'An error occurred while adding user to the database: %s' % (str(err))
        except Exception, err:
            context['failure'] = '%s' % (str(err))

   return json_response(context)

:在这种情况下交易将如何运作?在这里显式使用事务会更好吗?

更新

就我而言,我使用的是继承模型类。示例:

class BaseUser(models.Model)
   first_name = models.CharField(max_length=100)
   last_name = models.CharField(max_length=100)
   email = models.EmailField(max_length=100, unique=True)


class UserA(BaseUser):
   phone = models.BigIntegerField()
   type = models.CharField(max_length=32)

因此,如果我尝试使用上述视图创建 UserA 类型对象并引发异常,则 BaseUSer 对象是使用给定数据创建的,但 UserA 类型对象不是。所以,我想做的是要么创建TypeA 对象,要么不提交任何更改。目前我正在手动使用事务(如下),它似乎工作正常,只是我想改用对 HTTP 请求使用事务。

from django.db import transaction


transaction.commit_on_success()
def some_view(request):
    """ Creates a user object.
    """

    context = {}
    data = # Read from file

    for row in data:
        first_name, last_name, email = row.split(",")

        try:
            sid = transaction.savepoint()
            create_user(first_name, last_name, email)
            context['success'] = 'User %s was added to the database.' % (first_name)
            transaction.savepoint_commit()
        except IntegrityError, err:
            context['failure'] = 'An error occurred while adding user to the database: %s' % (str(err))
            transaction.savepoint_rollback()
        except Exception, err:
            transaction.savepoint_rollback()
            context['failure'] = '%s' % (str(err))

   return json_response(context)

【问题讨论】:

    标签: mysql django http transactions request


    【解决方案1】:

    这里根本不需要交易。如果引发 IntegrityError,则意味着数据库更新甚至无法完成,因此无需回滚。

    如果您想在单个更新失败时回滚所有更新,则事务非常有用。

    【讨论】:

    • 在我的情况下,user 模型类使用继承,所以当我尝试使用无效数据为父类中的字段创建多个对象时,创建了子类对象但父类类不是..为什么会这样?
    • 您可以在我的问题中查看更新,以便更好地了解我的问题,谢谢。
    猜你喜欢
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-12
    相关资源
    最近更新 更多