我想验证并保存一个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
,如果有任何不通过验证,请允许我这样做吗?或者是否有另一种更好的方法来验证和保存"树中的数据。结构
答案 0 :(得分:1)
你为每个叶子调用form.save()
的事实看起来很奇怪:通常你会验证整个事物一次(递归或不递归),然后保存一次。惯用方法是在自定义表单类中使用validate()
和save()
方法以及standard POST
view。
那就是说,我假设您确实需要某种递归数据库保存。在那种情况下:
try
条款should surround 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)