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

时间:2015-03-19 16:13:17

标签: 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': '',
    }
}

没有特殊的交易中间件。

我发现以下观点特别令人费解。 (编者)

@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')

其中initialize_xml_model是一个获取平面xml文件(xml模型模板)并创建新XMLModel对象的函数。并且insert_user_info将存储在用户对象中的信息插入到xml模型中。

我读这段代码的方式是

  1. 我们使用autocommit
  2. 关闭commit_manually
    • 我们要么为用户获取最新的XMLModel对象,要么
    • 初始化一个新的XMLModel对象
  3. 如果没有错误,
  4. transaction.commit()会将其存储到数据库中。
  5. 我们检查我们的model是否是一个unicode实例,然后对其进行编码(我不知道这究竟是什么)
  6. 我们开了一个新交易
  7. 使用model
  8. 实现XMLManipulator对象
  9. 插入内容并清理xml
  10. 将xml实例作为字符串分配回modeltostring是一个保留样式表声明的XMLManipulator方法。)
  11. 删除xml对象
  12. 提交交易
  13. 在5.之后,唯一处理db(在读取中)的是insert_user_info方法。

    我真的不明白为什么在特殊交易中会发生这种情况。没有写入db?

    此视图中没有其他方法,只有get。

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

    此处交易是否真的有必要,如果是,那怎么可以重写以适应新的transaction.set_autocommit

    非常感谢任何帮助或指示。

1 个答案:

答案 0 :(得分: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')