如果尚未保存在服务器上,如何回滚数据库查询?

时间:2015-12-14 11:07:01

标签: python django

当我需要在服务器上保存文件并将相应的记录放入数据库时​​,我有功能。我怎样才能确保两个事件都发生?

目前我有以下逻辑,但是有更好的解决方案吗?

def handle_uploaded_file(filename, file_content, request):
    # Saves file on the server
    try:
        path_to_file = '{}/{}'.format(settings.REPORTS_FOLDER, filename)
        with open(path_to_file, 'wb+') as destination:
            for chunk in file_content.chunks():
                destination.write(chunk)
    except IOError:
        raise
    # Saves info about uploaded file in the database
    try:
        with transaction.atomic():
            new_report = Reports(
                path_to_file=path_to_file,
                document_name=filename,
                author=request.user,
                document_type=request.POST['report_type']
                )
            new_report.save()
    except IntegrityError:
        os.remove(path_to_file)
        raise

1 个答案:

答案 0 :(得分:0)

请考虑以下代码:

from django.db import transaction

@transaction.atomic
def handle_uploaded_file(filename, file_content, request):
    path_to_file = '{}/{}'.format(settings.REPORTS_FOLDER, filename)

    save_file_metadata(filename, path_to_file, request)
    write_file_contents(file_content, path_to_file)


def write_file_contents(file_content, path_to_file):
    try:
        with open(path_to_file, 'wb+') as destination:
            for chunk in file_content.chunks():
                destination.write(chunk)
    except IOError:
        os.remove(path_to_file)
        raise


def save_file_metadata(filename, path_to_file, request):
    new_report = Reports(
            path_to_file=path_to_file,
            document_name=filename,
            author=request.user,
            document_type=request.POST['report_type']
    )
    new_report.save()

优点是您首先将元数据保存在数据库中(根据我的理解样本,可以抛出)。如果它抛出,交易将无法完成,也不会存储任何内容。

如果操作系统写入抛出,则重新引发异常后将无法完成数据库事务。

文件清理,但看起来我需要做更多的工作才能完全安全地保护。