如何在Django Admin action中使用queryset.update更新外键关联字段
问题解答
Django ORM的queryset.update()方法不支持直接通过双下划线__语法跨外键更新关联表字段,你收到的报错正是该限制导致的。
原因说明
update()方法仅支持更新当前queryset对应模型的自有字段,双下划线的关联查询语法仅在filter()、exclude()、annotate()等数据查询类方法中生效,无法用于update()的字段赋值参数。
解决方案
你可以选择以下两种方案实现需求:
方案一:分步骤批量更新(适合大数据量,性能更高)
分别对当前Order模型和各个关联外键模型执行批量更新操作:
def staff_reset(self, request, queryset): # 1. 更新Order表自有字段 updated = queryset.update(regstatus='registered') # 2. 批量更新各关联外键表字段 MedicalForm.objects.filter(order__in=queryset).update(medform_status='required') StaffMonitoringForm.objects.filter(order__in=queryset).update(monitoring_status='required') StaffReleaseForm.objects.filter(order__in=queryset).update(release_status='required') StaffEthicsForm.objects.filter(order__in=queryset).update(ethics_status='required', i_agree=False) self.message_user(request, ngettext( '%d staff registration was successfully reset.', '%d staff registrations were successfully reset.', updated, ) % updated, messages.SUCCESS) staff_reset.short_description="Reset Staff Registrations"
方案二:遍历逐个更新(适合小数据量,需触发模型save方法/信号场景)
如果你的业务逻辑依赖模型的save()方法或者pre_save、post_save等信号,可以遍历queryset逐个更新:
def staff_reset(self, request, queryset): updated = 0 for order in queryset: order.regstatus = 'registered' # 更新关联字段前先判断关联对象是否存在,避免空值报错 if order.medicalform: order.medicalform.medform_status = 'required' order.medicalform.save() if order.staffmonitoringform: order.staffmonitoringform.monitoring_status = 'required' order.staffmonitoringform.save() if order.staffreleaseform: order.staffreleaseform.release_status = 'required' order.staffreleaseform.save() if order.staffethics: order.staffethics.ethics_status = 'required' order.staffethics.i_agree = False order.staffethics.save() order.save() updated += 1 self.message_user(request, ngettext( '%d staff registration was successfully reset.', '%d staff registrations were successfully reset.', updated, ) % updated, messages.SUCCESS) staff_reset.short_description="Reset Staff Registrations"
注意事项
- 你的所有外键字段都配置了
null=True,更新关联字段前建议先判断关联对象是否存在,避免抛出AttributeError。 - 方案一的批量更新操作不会触发单个模型的
save()方法和关联信号,如有相关业务依赖请选择方案二。
内容的提问来源于stack exchange,提问作者Peterkm
相关产品推荐
相关产品推荐

