如何使用django TransactionMiddleware与MySQL数据库

时间:2014-01-21 10:05:12

标签: mysql django http transactions request

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

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)

:在这种情况下,交易将如何运作?在这里明确使用交易是否更好?

更新

在我的情况下,我使用的是Inherited模型类。例如:

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)

1 个答案:

答案 0 :(得分:0)

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

如果您希望在单个更新失败时回滚所有更新,则交易非常有用。