如何在Django inlineformset_factory全量保存后获取完整QuerySet
问题
现有模型关系如下:
class Model1(models.Model): field1 = models.CharField(max_length=4) class ChildToModel1(models.Model): model_1 = models.ForeignKey(Model1, related_name='model_1', on_delete=models.CASCADE)
为ChildToModel1创建inlineformset_factory后,Django会循环保存多个ChildToModel1实例。当前通过post_save信号监听时,每次保存仅能获取到截至当前已保存的部分QuerySet,输出如下:
<QuerySet [obj]> <QuerySet [obj][obj]> <QuerySet [obj][obj][obj]>
希望仅在所有实例保存完成后,获取完整的QuerySet:
<QuerySet [obj][obj][obj]>
请问如何实现该需求?
解决方案
方法1:在Formset保存后直接处理
放弃使用post_save信号,直接在视图中处理formset保存后的逻辑。调用formset.save()后,所有子实例已完成保存,此时通过关联的父模型实例即可获取完整的子对象QuerySet。
示例代码:
def your_view(request, pk): parent_obj = Model1.objects.get(pk=pk) ChildFormSet = inlineformset_factory(Model1, ChildToModel1, fields=('...',)) if request.method == 'POST': formset = ChildFormSet(request.POST, instance=parent_obj) if formset.is_valid(): # 保存所有子实例 formset.save() # 获取完整的子对象QuerySet full_queryset = parent_obj.model_1.all() # 在这里执行你的后续逻辑,比如打印、数据处理等 print(full_queryset) # 其他视图逻辑...
方法2:利用事务提交信号
Django的transaction.on_commit()方法会在当前事务提交后执行回调函数,而inlineformset的默认保存操作会在一个事务内完成所有实例的保存。通过这个方法可以确保所有子实例都已持久化后再处理完整QuerySet。
示例代码:
from django.db import transaction def your_view(request, pk): parent_obj = Model1.objects.get(pk=pk) ChildFormSet = inlineformset_factory(Model1, ChildToModel1, fields=('...',)) if request.method == 'POST': formset = ChildFormSet(request.POST, instance=parent_obj) if formset.is_valid(): # 定义事务提交后的回调逻辑 def after_all_saved(): full_queryset = parent_obj.model_1.all() print(full_queryset) # 绑定回调,事务提交后执行 transaction.on_commit(after_all_saved) # 保存formset formset.save() # 其他视图逻辑...
方法3:在post_save信号中判断是否为最后一个实例
如果必须使用post_save信号,可以在信号处理函数中对比当前已保存的子实例数量与formset的总实例数,当两者相等时再处理完整QuerySet。不过这种方法需要传递formset的总数量到信号中,实现相对繁琐,推荐优先使用前两种方法。
内容的提问来源于stack exchange,提问作者Cynthia Onyilimba
相关产品推荐
相关产品推荐

