Django循环中使用update_or_create时部分字段值重复异常排查
先确认过滤条件的有效性
你用sku作为update_or_create的过滤条件,但要先核实API返回的变体数据里,sku是否真的和每个变体一一对应。如果存在多个变体共享同一个sku的情况,update_or_create会持续更新同一条数据库记录,最终所有变体的ID都会被覆盖成最后一次循环的取值。建议在循环里额外打印每个变体的sku,和对应的product_id、variant_id做比对,确认sku的唯一性。检查ID字段的赋值逻辑
排查嵌套循环中,shopify_product_id和shopify_variant_id的赋值是否误用了外部变量。比如外层循环的product_id变量没有被内层变体数据正确覆盖,导致所有变体都用同一个product_id写入数据库。举个反例:for product in products: outer_product_id = product['id'] for variant in product['variants']: # 错误:误用外层的product_id,而非变体自身的product_id Variant.objects.update_or_create( sku=variant['sku'], defaults={ 'shopify_product_id': outer_product_id, 'shopify_variant_id': variant['id'], 'name': variant['name'], 'price': variant['price'] } )确保赋值时使用的是
variant['product_id'],哪怕理论上它和外层product_id一致,也要以变体自身返回的字段为准。排查数据库字段约束
检查模型中shopify_product_id、shopify_variant_id是否设置了unique=True或联合唯一约束。如果有这类约束,而旧数据中存在冲突,会导致update_or_create的逻辑异常。另外,确认sku的唯一约束是否真的生效——比如模型里是否给sku字段加了unique=True,迁移是否已执行。验证循环变量作用域
有时候循环变量的延迟绑定会导致值被意外覆盖,可以在循环内先把变体的ID值存入局部变量,再传入方法:for variant in product['variants']: current_product_id = variant['product_id'] current_variant_id = variant['id'] Variant.objects.update_or_create( sku=variant['sku'], defaults={ 'shopify_product_id': current_product_id, 'shopify_variant_id': current_variant_id, 'name': variant['name'], 'price': variant['price'] } )查看实际执行的SQL语句
开启Django的数据库查询日志,跟踪每次update_or_create执行的SQL,确认过滤条件和更新字段的取值是否正确:import logging db_logger = logging.getLogger('django.db.backends') db_logger.setLevel(logging.DEBUG) db_logger.addHandler(logging.StreamHandler())通过日志可以直接看到ORM生成的INSERT/UPDATE语句,对比传入的参数和实际写入数据库的值,快速定位问题出在数据赋值还是ORM逻辑层面。
内容的提问来源于stack exchange,提问作者VIDesignz

