将transaction.commit_manually()升级到Django> 1.6

seb*_*seb 8 python xml django transactions django-1.7

我继承了为Django 1.4编写的应用程序的一些代码.我们需要更新代码库以使用Django 1.7,并最终将1.8作为下一个长期支持版本.

在一些地方,它使用旧的风格@transaction.commit_manuallywith transaction.commit_manually:

我对一般的交易了解不多,但我想了解它们的用途,所以我可以删除它们(如果没有必要)或将它们升级到更新set_autocommit(False)或等效的.

我已经理解Django <1.5中的事务管理并不理想,并且对于大多数用例来说太复杂了.

数据库连接如下所示,没有特殊的事务管理.(使用Postgres 9.3)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'dbname',
        'USER': 'user',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '',
    }
}
Run Code Online (Sandbox Code Playgroud)

没有特殊的交易中间件.

我发现以下观点特别令人费解.(编辑)的

@UserRequiredDecorator
class XMLModelView(View):

    @transaction.commit_manually
    def get(self, request, *args, **kwargs):
        user = request.user

        xml_models = models.XMLModel.objects.filter(user=user).order_by('-created').all()
        if xml_models:
            xml_model = xml_models[0]
            model = xml_model.xml_field
        else:
            obj = initialize_xml_model(user)
            model = obj.xml_field

        transaction.commit()
        if isinstance(model, unicode):
            model = model.encode('utf-8')

        with transaction.commit_manually():
            xml = XMLManipulator(model, remove_blank_text=True)
            xml.insert_user_info(user)
            xml.whitespace_cleanup()
            model = xml.tostring()
            del xml
            transaction.commit()
        return HttpResponse(model, content_type='text/xml')
Run Code Online (Sandbox Code Playgroud)

哪个initialize_xml_model函数采用平面xml文件(xml模型模板)并创建新的XMLModel对象.和insert_user_info插入存储在用户对象到XML模型信息.

我读这段代码的方式是

  1. 我们关掉autocommitcommit_manually
    • 我们要么为用户获取最新的XMLModel对象,要么
    • 初始化一个新的XMLModel对象
  2. transaction.commit() 如果没有错误,则将其存储到数据库.
  3. 我们检查我们model是否是一个unicode实例,然后对其进行编码(我不确定这是什么)
  4. 我们开了一个新的交易
  5. 用它来实现XMLManipulator对象 model
  6. 插入东西并清理xml
  7. 将xml实例分配回model字符串(tostring是一个保留样式表声明的XMLManipulator方法.)
  8. 删除xml对象
  9. 提交交易

在5.之后,处理db(在读取中)的唯一事情是insert_user_info方法.

我真的不明白为什么在特殊交易中发生这种情况.没有写入数据库?

此视图上没有其他方法,只有get.

我可能错过了一些重要的东西,随时提出任何问题或了解更多信息.

这里的交易真的有必要,如果是的话,怎么可以改写以适应新的交易transaction.set_autocommit呢?

任何帮助或指针将不胜感激.

小智 6

现在这样做的好方法是使用transaction.atomic.在你的例子中我会这样做:

from django.db import transaction

@UserRequiredDecorator
class XMLModelView(View):

    def get(self, request, *args, **kwargs):

        with transaction.atomic():
            user = request.user

            xml_models = models.XMLModel.objects.filter(user=user).order_by('-created').all()
            if xml_models:
                xml_model = xml_models[0]
                model = xml_model.xml_field
            else:
                obj = initialize_xml_model(user)
                model = obj.xml_field

        if isinstance(model, unicode):
            model = model.encode('utf-8')

        with transaction.atomic():
            xml = XMLManipulator(model, remove_blank_text=True)
            xml.insert_user_info(user)
            xml.whitespace_cleanup()
            model = xml.tostring()
            del xml

        return HttpResponse(model, content_type='text/xml')
Run Code Online (Sandbox Code Playgroud)