django_get_or_create无法创建实例:数组字段未填充问题求助
问题与解决方案
问题描述
我通过SubFactory使用ModelFactory,原本Meta类的django_get_or_create参数仅包含('code')。为模型新增两个数组字段后将它们加入该参数,现在出现两个问题:
- 无法创建code为'RU'的实例,测试中多次输出Turkey(TR的别名)
- 新增的数组字段未填充,输出空数组
[]
相关代码:
class ModelFactory(DjangoModelFactory): code = "RU" predefined_amounts_one_time = [500, 1000, 3000] predefined_amounts_recurring = [500, 1000, 3000] class Meta: model = Model django_get_or_create = ("predefined_amounts_one_time", "predefined_amounts_recurring", "code")
问题原因
- 数组字段无法作为
django_get_or_create的查询条件:Django ORM对数组类型字段(比如PostgreSQL的ArrayField)的比对支持有限,get_or_create尝试用数组字段查询时,无法匹配到预设的[500,1000,3000],导致查询失败。 - 查询失败后的逻辑冲突:查询不到匹配记录时,Factory可能触发了其他关联逻辑(比如SubFactory中已存在TR的实例),返回了Turkey的记录而非新创建的RU实例。
- 数组字段未填充:由于查询失败后创建新实例的流程异常,预设的数组字段默认值没有被正确传入模型。
解决方案
方案1:移除django_get_or_create中的数组字段
数组字段不适合作为唯一查询标识,保留code作为唯一键即可:
class ModelFactory(DjangoModelFactory): code = "RU" predefined_amounts_one_time = [500, 1000, 3000] predefined_amounts_recurring = [500, 1000, 3000] class Meta: model = Model django_get_or_create = ("code",)
方案2:手动处理get_or_create逻辑(需确保数组字段唯一性时用)
如果必须保证code和数组字段的组合唯一,重写Factory的_create方法,手动实现查询、创建或更新逻辑:
class ModelFactory(DjangoModelFactory): code = "RU" predefined_amounts_one_time = [500, 1000, 3000] predefined_amounts_recurring = [500, 1000, 3000] class Meta: model = Model @classmethod def _create(cls, model_class, *args, **kwargs): # 仅用code查询,数组字段作为默认值传入 obj, created = model_class.objects.get_or_create( code=kwargs["code"], defaults={ "predefined_amounts_one_time": kwargs["predefined_amounts_one_time"], "predefined_amounts_recurring": kwargs["predefined_amounts_recurring"], } ) # 若实例已存在,检查数组字段是否匹配,不匹配则更新 if not created: need_update = False if obj.predefined_amounts_one_time != kwargs["predefined_amounts_one_time"]: obj.predefined_amounts_one_time = kwargs["predefined_amounts_one_time"] need_update = True if obj.predefined_amounts_recurring != kwargs["predefined_amounts_recurring"]: obj.predefined_amounts_recurring = kwargs["predefined_amounts_recurring"] need_update = True if need_update: obj.save() return obj
方案3:检查SubFactory关联逻辑
排查SubFactory的代码,确认是否有逻辑覆盖了RU实例的创建,导致错误返回TR的Turkey记录。
内容的提问来源于stack exchange,提问作者Paul Allen
相关产品推荐
相关产品推荐

