Django的update_or_create方法传入多defaults字段报错如何解决?
问题原因
update_or_create方法的defaults参数仅支持传入单个字典结构,你当前传入的是由多个独立单键字典组成的元组,Django在执行字段更新逻辑时会调用defaults.items()读取字段键值对,元组没有对应方法,因此抛出'tuple' object has no attribute 'items'错误,使用列表包裹多个字典也会触发同类错误。
官方文档提到的解决字段增多时代码臃肿的特性,指的是无需手动编写try-except分支判断实例是否存在、分别执行创建和更新逻辑,并非支持传入多个字典,单个字典本身就支持传入任意数量的字段,不会因为字段多导致代码额外臃肿。
正确写法
把所有需要更新的字段统一放到同一个字典中传入defaults参数即可,修正后的代码如下:
def form_valid(self, form): form.instance.user = self.request.user form.instance, created = MyModel.objects.update_or_create( user=self.request.user, defaults={ 'field1': form.instance.field1, 'field2': form.instance.field2, 'field3': form.instance.field3, } ) return super().form_valid(form)
优化建议
如果需要更新的字段数量较多,可以直接从表单的清洗数据中批量提取需要的字段,避免手动逐个书写键值对,示例如下:
# 提前定义需要更新的字段列表 UPDATE_FIELDS = ['field1', 'field2', 'field3'] def form_valid(self, form): form.instance.user = self.request.user form.instance, created = MyModel.objects.update_or_create( user=self.request.user, defaults={k: v for k, v in form.cleaned_data.items() if k in UPDATE_FIELDS} ) return super().form_valid(form)
内容的提问来源于stack exchange,提问作者Doug Smith
相关产品推荐
相关产品推荐

