在Django Factory Boy中为每个测试重置主键(pk)序列
解决Django中Factory Boy测试时重置模型主键序列的问题
方法1:显式调用Factory的序列重置方法
在每个测试类的初始化方法中,手动重置Factory的主键序列,同时针对数据库层面的自增序列做同步重置(部分数据库如PostgreSQL需要这一步):
修改测试代码如下:
from django.db import connection from your_app.factories import ProfileFactory class FirstTest(TestCase): @classmethod def setUpClass(cls): super().setUpClass() # 重置Factory的主键起始序列为1 ProfileFactory.reset_sequence(1) # 重置数据库自增序列(替换为你实际的序列名) with connection.cursor() as cursor: cursor.execute("ALTER SEQUENCE your_app_profile_id_seq RESTART WITH 1;") ProfileFactory.create() ProfileFactory.create() class SecondTest(TestCase): @classmethod def setUpClass(cls): super().setUpClass() ProfileFactory.reset_sequence(1) with connection.cursor() as cursor: cursor.execute("ALTER SEQUENCE your_app_profile_id_seq RESTART WITH 1;") ProfileFactory.create() ProfileFactory.create()
序列名格式通常为
{app名称}_{模型名称}_id_seq,需要根据你的项目实际情况替换。
方法2:封装通用重置函数
为避免重复代码,可把重置逻辑封装成工具函数:
from django.db import connection def reset_model_sequence(model, start_value=1): # 重置对应Factory的序列 model._meta.factory_class.reset_sequence(start_value) # 生成数据库序列名并执行重置 sequence_name = f"{model._meta.app_label}_{model._meta.model_name}_id_seq" with connection.cursor() as cursor: cursor.execute(f"ALTER SEQUENCE {sequence_name} RESTART WITH {start_value};")
之后在测试中直接调用:
class FirstTest(TestCase): @classmethod def setUpClass(cls): super().setUpClass() reset_model_sequence(Profile) ProfileFactory.create() ProfileFactory.create()
方法3:适配不同数据库的差异
不同数据库的自增序列重置语法有区别,可按需调整:
- MySQL:将SQL语句改为
ALTER TABLE your_app_profile AUTO_INCREMENT = 1; - SQLite:事务回滚后序列会自动重置,仅需调用
ProfileFactory.reset_sequence(1)即可,如需手动重置可执行DELETE FROM sqlite_sequence WHERE name='your_app_profile';
内容的提问来源于stack exchange,提问作者Mateusz
相关产品推荐
相关产品推荐

