Django遍历模型字段数组 基于指定keys实现get_or_create逻辑
问题描述
我定义了如下Django模型:
class Some_model(models.Model): field_1 = models.CharField(max_length=200, blank=True, null=True) field_2 = models.CharField(max_length=200, blank=True, null=True)
同时编写了可接收JSON对象为模型实例赋值的工具函数,当前函数代码如下:
# create a function to upload a model object given a json object def upload_object_values(model, json_values, keys=None): if json_values: # assign a value to each key which is a the field in the given model for key, value in json_values.items(): setattr(model, key, value) # if the object has keys to check if keys: # check if exists using the keys
当按照如下方式调用该函数时:
upload_object_values(Some_model(), {'field_1': 'val', 'field_2': 'val_2'}, ['field_2'])
需要在upload_object_values函数内部,基于keys参数传入的字段列表(例如示例中传入的field_2)执行get_or_create操作,实现效果等同于直接执行以下语句:
Some_model.objects.get_or_create(field_2='val_2')
功能补充说明:
需要补全上述函数的剩余逻辑,实现该需求。
实现代码
补全后的完整函数如下,完全兼容原有调用方式,逻辑和Django原生get_or_create对齐:
def upload_object_values(model, json_values, keys=None): if not json_values: return model, False # 先给传入的临时实例赋全量字段值 for key, value in json_values.items(): setattr(model, key, value) # 未传入去重键时直接保存当前实例 if not keys: model.save() return model, True # 组装get_or_create的查询参数:仅用keys指定的字段做匹配 query_params = {key: getattr(model, key) for key in keys} # 组装新建时的默认值:非查询键的字段仅在新建时写入 create_defaults = {k: v for k, v in json_values.items() if k not in keys} # 通过实例的__class__属性拿到对应模型类,执行get_or_create target_obj, is_created = model.__class__.objects.get_or_create( **query_params, defaults=create_defaults ) # 如果匹配到已有记录,将JSON中的新值更新到该记录后保存 if not is_created: for key, value in json_values.items(): setattr(target_obj, key, value) target_obj.save() return target_obj, is_created
逻辑说明
- 不需要额外修改入参,通过传入的模型实例的
__class__属性即可获取对应的模型类,和示例中直接调用Some_model.objects.get_or_create的效果完全一致 - 查询参数严格从传入的
keys列表提取,不会用其他字段做匹配,避免误查 - 非查询字段统一放入
defaults参数,仅在新建记录时作为初始化值;如果是已存在的记录,会全量更新JSON中传入的字段值,符合工具函数的赋值定位 - 返回值和Django原生
get_or_create保持一致,返回(处理后的模型实例, 是否为新建记录)的元组,方便上层逻辑做后续判断
内容的提问来源于stack exchange,提问作者Prosy A.
相关产品推荐
相关产品推荐

