Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用transaction.atomic回滚递归表单验证+;拯救_Python_Django_Recursion - Fatal编程技术网

Python 使用transaction.atomic回滚递归表单验证+;拯救

Python 使用transaction.atomic回滚递归表单验证+;拯救,python,django,recursion,Python,Django,Recursion,我想递归地验证和保存json“树”(process\u response下面的函数)。如果树中的任何叶子无效,我想回滚到目前为止保存的所有叶子。以下是我的方法示例: @staticmethod def process_response(post_data): """ brief pseudocode function to illustrate resursive form.save() """ if is_leaf is True: if not form.is

我想递归地验证和保存json“树”(
process\u 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

transaction.atomic
中包装对
process\u response
的调用并引发
DatabaseError
是否允许我这样做?或者有没有其他更好的方法来验证和保存“树”结构中的数据?

为每个叶调用
form.save()
,这一事实似乎很奇怪:通常情况下,您会验证整个内容一次(递归或不递归),然后保存一次。惯用的方法是在自定义表单类上结合使用
validate()
save()
方法

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

  • try
    子句用于
    atomic()
    事务
  • DatabaseError
    保留到数据库中。使用更合适的方法,如
    ValueError
    ValidationError
  • 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)

如果抛出的异常不是
DatabaseError
或其子类,transaction.atomic是否回滚?关于第一次验证和第二次保存,我实际上事先不知道树有多大(就我而言,它只有一个分支深,但我不知道有多少分支),因此在验证时我必须记录树的结构。此外,并非所有叶片都是相同的
型号
类型。我认为递归保存在这种情况下更具可读性。例如,请参阅关于在
atomic()
中避免捕获异常的部分:示例使用
DatabaseError
subclasses@Escher:是,事务在任何异常时回滚。