使用transaction.atomic回滚递归表单验证+保存

时间:2018-01-06 09:37:48

标签: python django recursion

我想验证并保存一个json"树"递归(process_response函数如下)。如果树中的任何叶子无效,我想回滚到目前为止所有已保存的叶子。这是我的方法的一个例子:

@staticmethod
def process_response(post_data):
    """ brief pseudocode function to illustrate resursive form.save() """
    if is_leaf is True:
        if not form.is_valid():
            return HttpResponse(status=400)
        else:
            form.save(post_data)
            return HttpResponse(status=200)
    else: # is not a leaf, so must be a branch
        for child_data in post_data.children
            result = MyClass.process_response(child_data)
            if result.status_code != 200:
                return result

def post(self, request, *args, **kwargs):
    post_data = process_post_data(request) # json decoding, validation, etc
    with transaction.atomic():
        try:
            result = MyClass.process_response(post_data)
            if result.status_code != 200:
                raise DatabaseError
        except:
            return result
    return result

将来自process_response的{​​{1}}功能的电话打包并提出transaction.atomic,如果有任何不通过验证,请允许我这样做吗?或者是否有另一种更好的方法来验证和保存"树中的数据。结构

1 个答案:

答案 0 :(得分:1)

你为每个叶子调用form.save()的事实看起来很奇怪:通常你会验证整个事物一次(递归或不递归),然后保存一次。惯用方法是在自定义表单类中使用validate()save()方法以及standard POST view

那就是说,我假设您确实需要某种递归数据库保存。在那种情况下:

  • try条款should surround atomic()交易。
  • DatabaseError留给数据库。使用更合适的内容,例如ValueErrorValidationError
  • HttpResponse留给调用函数,没有理由将这样的问题混合到递归函数中。

我的伪代码看起来像:

def validate_and _save(data):
    if is_leaf:
        if not valid:
            raise ValueError()
        else:
            save_leaf()
    else:
        for child in children:
            validate_and _save(child)

def post(self, request, *args, **kwargs):
    post_data = process_post_data(request)

    try:
        with transaction.atomic():
            validate_and_save(post_data)
    except ValueError:
        return HttpResponse(status=400)
    else:
        return HttpResponse(status=200)