pytest 默认无法运行 django 测试,因其不自动调用 django.setup() 或加载 settings,需 pytest-django 插件配合正确配置(如 django_settings_module、pytest.ini 位置及内容)和 db fixture 才能正常执行。

直接用 pytest 运行 Django 测试会报 django.core.exceptions.ImproperlyConfigured: Requested setting DEBUG, but settings are not configured——根本原因是没加载 Django 配置,不是代码写错了。
为什么 pytest 默认跑不起来 Django 测试
pytest 本身完全不知道 Django 的存在。它不会自动调用 django.setup(),也不会读取 settings.py 或初始化数据库连接。错误信息里出现的 DATABASES、DEBUG、INSTALLED_APPS 等,全是因为测试函数里(或 import 阶段)提前触碰了 Django 的配置项,而此时框架还没启动。
必须靠 pytest-django 插件 + 显式配置驱动整个流程,缺一不可。
- 不装
pytest-django:pytest 当普通 Python 脚本跑,ORM 直接瘫痪 - 没设
DJANGO_SETTINGS_MODULE:插件找不到配置入口,报错位置可能在 import models 的第一行 - pytest.ini 不在项目根目录(即和
manage.py同级):pytest 找不到配置文件,退化为默认行为 - settings 模块路径写错(比如漏了
myproject.settings中的myproject):Python 导入失败,报ModuleNotFoundError
最简可用配置三步走
不需要改项目结构、不写 conftest.py、不碰 manage.py,三步就能让第一个 test_*.py 跑起来:
- 运行
pip install pytest-django - 在项目根目录(含
manage.py)新建pytest.ini,内容严格如下:[tool:pytest] DJANGO_SETTINGS_MODULE = myproject.settings python_files = test_*.py python_classes = Test* python_functions = test_*
其中myproject.settings必须替换成你真实的模块路径,比如blog.settings或config.settings.dev - 确保该路径能被 Python 导入:如果项目是
src/结构,加一行addopts = --pythonpath src到pytest.ini里
别在测试文件顶部就写 from myapp.models import MyModel —— 这会触发 ORM 初始化,早于 Django setup,必报错。把 import 放到测试函数内部,或用 @pytest.fixture 延后加载。
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
模型测试必须带 db fixture
写了 MyModel.objects.create() 却发现查不到数据、或报 DatabaseWrapper is not accessible before django.setup(),大概率是漏了 db fixture。
-
def test_user_creation(db):→ 正确。事务级隔离,速度快,适合字段校验、save()行为、get_absolute_url()等 -
def test_user_creation():→ 错误。没 fixture,数据库操作被跳过,create()不生效,后续assert全是空转 -
def test_post_save_signal(transactional_db):→ 用于需要真实提交事务的场景,比如测试post_save信号、外键级联删除
不要手动调用 call_command('migrate'),pytest-django 已在 setup 阶段根据模型自动生成 schema;重复 migrate 会触发 Relation "xxx" already exists。
API 测试 client 返回 404 或 500 的真实原因
不是路由配错了,也不是视图写崩了——而是 client 没走对初始化路径。
- 别自己实例化
Client():它不会自动注入session、request.user,也不绕 CSRF - 直接用 pytest-django 提供的
clientfixture:def test_api_list(client): response = client.get('/api/users/') - 要登录?用
client.login(username='x', password='y'),比手动塞 session 可靠 - 要跳过 CSRF?在测试函数上加
@pytest.mark.django_db不够,得配csrf_client = client或改用APIRequestFactory(DRF 场景)
最容易被忽略的是:测试文件名必须匹配 pytest.ini 里的 python_files 规则(默认是 test_*.py),写成 tests.py 或 api_test.py 会被 pytest 完全忽略——连报错都不会有,静默跳过。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










