一、Django 项目单元 & 集成测试准备 👇

依赖安装(给项目装 “测试小帮手”🍼)

pdm add -d black isort flake8 pytest pytest-django pytest-coverage  

👉 这行命令像在给项目 “采购” 测试工具:

  • black ✨ 自动格式化代码,让代码整齐得像排好队的小士兵
  • isort 🧹 帮你把 import 语句整理得明明白白
  • flake8 🔍 像代码 “小侦探”,揪出语法和风格问题
  • pytest 🧪 单元测试 “大主角”,跑测试用例超好用
  • pytest-django 🐍+🧪 让 pytest 能和 Django 好好 “交朋友”,测试 Django 项目
  • pytest-coverage 📊 看看测试覆盖了多少代码,心里有底

 

配置文件(给工具们定 “小规矩”📜)

1. .flake8(flake8 的 “小手册”)
[flake8]  
exclude = venv  # 告诉 flake8 别去碰 venv 文件夹~🚫  
extend-ignore = E501  # 放宽点啦,忽略行太长的报错(E501)🙈  
2. pytest.ini(pytest 的 “剧本”)
[pytest]  
DJANGO_SETTINGS_MODULE = Tesla.settings  # 告诉 pytest 用哪个 Django 配置⚙️  
python_files = tests.py test_*.py  # 哪些文件算测试文件呀?找 tests.py 和 test_开头的~🔍  

测试用例(给项目 “模拟闯关”🎮)

根据我们的业务逻辑代码进行分析~

 

1. 注册功能 📝
  • 允许匿名访问 👻(游客也能注册!)
  • URL:http://127.0.0.1:8000/accounts/register 🔗
    • GET:返回 HTML 页面~像打开注册 “小窗口”🖥️
    • POST:提交 JSON 数据,还要验证:
      • 用户名不能为空 ❌(空用户名像没名字的小幽灵,不行!)
      • 密码不能为空 ❌(没密码咋保护自己~)
      • 两次密码得一样 🔄(不然自己都记混啦)
      • 密码长度≥6 位 📏(太短不安全呀)
      • 用户名不能重复 👥(不能撞名呀)
      • 都对的话,返回 “注册成功”🎉

 

2. 登录功能 🔑
  • 允许匿名访问 👻(游客也能登录页逛逛)
  • URL:http://127.0.0.1:8000/accounts/login/ 🔗
    • GET:返回登录 HTML 页面 🖥️
    • POST:提交表单,还要验证:
      • 用户名不能为空 ❌(没用户名咋找账号~)
      • 密码不能为空 ❌(没密码进不去呀)
      • 用户名、密码得对 ✅(不然进错家门啦)

 

3. 提交反馈 📮
  • 不允许匿名访问 🔒(得登录才能反馈!)
  • URL:http://127.0.0.1:8000/beifan/submit 🔗
    • GET:返回 HTML 页面 🖥️
    • POST:提交 JSON 数据,还要验证:
      • 数据能存到数据库里 🗄️(像把信放进邮箱~)
      • 数据和用户关联上 👤(谁发的反馈要记好)
      • 同一用户不能重复发 🔄(别刷屏呀~)

4. 反馈结果 🔍
  • 允许匿名访问 👻(谁都能看看结果)
  • URL:http://127.0.0.1:8000/beifan/result 🔗
  • 不管 GET/POST,都返回 HTML 页面 🖥️(看看反馈结果啥样~)

二、HttpResponse

数据结构角度

HttpResponse定义了一系列属性和方法来管理响应相关的数据。

  • 属性方面
    • content:以字节串形式存储响应的主体内容,比如返回的 HTML 页面内容、JSON 数据经过编码后的字节串等。例如返回一个简单 HTML 页面,这个 HTML 文本内容最终会编码后存到content中。
    • status_code:记录 HTTP 响应状态码,像常见的200(请求成功)、404(页面未找到)、500(服务器内部错误)等,通过这个属性可以让客户端快速知晓请求处理的结果状态。
    • headers:是一个类似字典的数据结构,用来存放 HTTP 响应头信息,比如Content - Type(指定响应内容的类型,像text/html表示 HTML 页面,application/json表示 JSON 数据)、Content - Length(响应内容的长度)等。
  • 方法方面
    • 它提供了一些方法来操作响应数据,比如__setitem__方法(可以像操作字典一样response['key'] = 'value'),用于设置响应头信息。

 

面向对象角度

HttpResponse类遵循面向对象编程范式,通过封装、继承和多态等特性,来实现对 HTTP 响应的管理和扩展:

  • 封装:把与 HTTP 响应相关的各种信息(内容、状态码、响应头)和操作(设置响应头、获取内容等)封装在一个类中,提供了统一且便捷的接口来处理响应。比如在视图函数中,只需要创建HttpResponse实例并设置相关属性,就能轻松构建一个完整的 HTTP 响应。
  • 继承:Django 提供了一些HttpResponse的子类,如HttpResponseRedirect(用于重定向,默认状态码为302)、JsonResponse(专门用于返回 JSON 数据,自动设置Content - Typeapplication/json ) 。这些子类继承了HttpResponse的基本属性和方法,并根据自身功能需求进行了扩展和定制。
  • 多态:在 Django 的视图函数返回机制中,无论是返回HttpResponse对象还是它的子类对象,都遵循统一的规则(都被视为合法的响应返回值),这体现了多态性。视图函数根据业务逻辑的不同,灵活返回不同类型的响应对象,而 Django 的请求处理机制都能正确处理并发送给客户端。

 

Web 开发流程角度

在 Django 应用处理 HTTP 请求的流程中,HttpResponse是请求处理结果的最终承载者:

  • 当客户端发起一个 HTTP 请求到 Django 服务器,Django 会根据 URL 配置找到对应的视图函数进行处理。
  • 视图函数在处理完业务逻辑(如查询数据库、进行数据计算等)后,需要构建一个响应返回给客户端,此时就会创建HttpResponse对象(或者它的子类对象),将处理结果填充到响应对象的相关属性中(如设置响应内容、状态码、响应头)。
  • 最后,Django 的请求处理机制会将这个HttpResponse对象转换为符合 HTTP 协议规范的格式,通过网络发送给客户端,客户端再根据响应信息进行相应的展示或处理(如浏览器渲染 HTML 页面、解析 JSON 数据等) 。

总之,HttpResponse类是 Django 构建和管理 HTTP 响应的核心组件,通过数据结构、面向对象编程以及在 Web 开发流程中的关键作用,实现了从服务器端到客户端的响应信息传递。

三、测试HTTP请求 

先测试一个简单的登录视图的get请求(返回一个html页面)

from django.test.client import Clientimport pytest@pytest.fixture
def client() -> Client:return Client()def test_register_get(client: Client):resp: HttpResponse = client.get("/accounts/register")assert resp.status_code == 200html = resp.content.decode()assert "html" in htmlassert "用户名" in htmlassert "密码" in htmlassert "确认密码" in html

 

1. 引入工具:from django.test.client import Client

👉 作用:从 Django 测试工具里,把「发 HTTP 请求的小助手 Client」请进来~
👀 为啥?
Django 专门给咱准备了 Client 类,用来模拟浏览器发请求(比如 GET、POST),测试咱的视图函数 / 接口。就像给代码一个 “虚拟小浏览器”,不用真的开浏览器,也能测试网页 / 接口响不响应~

 

2. fixture 魔法:@pytest.fixture + def client() -> Client:

@pytest.fixture  
def client() -> Client:  return Client()  

👉 作用:用 pytest 的 fixture,创建一个可复用的 “发请求工具”,叫 client
👀 为啥这么写?

  • @pytest.fixture 是 pytest 的 “魔法标记”🧙,标记后,这个 client 函数就变成了一个 “工具工厂”,其他测试函数要用的时候,直接当参数传进去就行!
  • return Client():每次调用 client,都会新建一个 Client 实例(也就是新的 “虚拟小浏览器”),保证测试之间互不干扰~

 

3. 测试用例:def test_register_get(client: Client):

👉 作用:定义一个测试用例,名字叫 test_register_get,专门测试注册页面的 GET 请求
👀 为啥参数是 client: Client
因为上面用 @pytest.fixture 标记了 client,pytest 会自动把 Client 实例传进来,供这个测试用例使用!相当于 “自动给你递上小浏览器,不用自己手动创建啦”~

 

4. 发请求:resp: HttpResponse = client.get("/accounts/register")

👉 作用:用 client(虚拟小浏览器),发一个 GET 请求 到 /accounts/register(注册页面的 URL),然后把服务器返回的响应存到 resp 里~
👀 为啥这么写?
模拟用户在浏览器里输入 http://.../accounts/register 访问注册页的行为。client.get(...) 就是帮我们发 GET 请求的 “快捷方式”,不用真的启动浏览器~

 

5. 断言状态码:assert resp.status_code == 200

👉 作用:检查服务器返回的状态码是不是 200200 代表 “请求成功”,网页正常返回啦~)
👀 为啥要断言?
测试的核心!如果状态码不是 200(比如 404 找不到页面、500 服务器报错),说明注册页面可能有问题,测试就会 “失败”,提醒咱去修~

 

6. 解析响应内容:html = resp.content.decode()

👉 作用:把响应的二进制内容(resp.content)转换成字符串(decode() 解码),方便后面检查页面里有没有我们要的内容~
👀 为啥要解码?

网络编程(发送和接收网络数据包)的HttpResponse是字节流,二进制数据。
resp.content 存的是二进制数据(像 b'<html>...'),转成字符串(html)后,才能用字符串的方法(比如 in 关键字)检查内容~

 

7. 检查页面内容:一堆 assert

assert "html" in html  
assert "用户名" in html  
assert "密码" in html  
assert "确认密码" in html  

👉 作用:确认返回的 HTML 里,包含 “html”“用户名”“密码”“确认密码” 这些关键字~
👀 为啥要检查?
保证注册页面的 HTML 里,确实有这些表单字段(用户名、密码输入框)。如果哪天代码不小心把这些字段删了,测试就会失败,提醒咱 “注册页面不对啦!”

 

四、测试DB数据库 

 

🌟 user fixture —— 提前造个 “测试用户”

@pytest.fixture()  
def user(_django_db_helper):  new_user = User.objects.create_user(  username='test_user',  email='test_user@qq.com',  password='test_user_pass',  )  return new_user  
逐行拆解
  • @pytest.fixture()

    • pytest 的 “魔法标记”🧙,标记后,user 就变成一个可复用的 “工具函数”,其他测试用例要用时,直接传参即可!
    • 作用:提前帮你在数据库里造一个测试用户,不用每次测试都手动创建啦~
  • def user(_django_db_helper):

    • _django_db_helper 是 pytest-django 提供的 “数据库小助手”,会自动帮你初始化、清理数据库,保证测试间互不干扰~
    • 函数名 user 是你给这个 “造用户工具” 起的名字,方便其他测试用例调用~
  • new_user = User.objects.create_user(...)

    • 调用 Django 的 create_user 方法,在数据库里实际创建一个用户(用户名、邮箱、密码都是测试用的假数据~)
    • 相当于:“嘿,数据库~ 帮我塞一条用户数据,测试时要用!”
  • return new_user

    • 把刚创建的用户对象返回,其他测试用例如果用了这个 user fixture,就能直接拿到这个 “测试用户” 啦~

 

🌟 参数化测试 —— 批量测 “注册场景”

这部分是用 @pytest.mark.parametrize 批量测试不同注册情况(用户名空、密码不一致、注册成功等),超高效!

@pytest.mark.parametrize(  "data, code, msg",  [  ({"username": ""}, -1, "username 不能为空"),  # 用户名空  ({"password_confirm": "2"}, -2, "两次密码输入不一致"),  # 密码不一致  ({"username": "test_user_beifan"}, 0, "注册成功"),  # 注册成功  ]  
)  
def test_register_post(user, client, data, code, msg):  # 发 POST 请求测试注册  resp = client.post(  "/accounts/register",  data=data,  content_type="application/json"  )  # 解析响应  html = resp.content.decode()  resp_json = json.loads(html)  # 断言响应是否符合预期  assert resp_json["code"] == code  assert resp_json["msg"] == msg  

这里的data有简化省略了其他的键值对 

逐行拆解
  • @pytest.mark.parametrize("data, code, msg", [...])

    • pytest 的 “参数化魔法”🪄!括号里的 "data, code, msg" 是 “参数名”,后面的列表是 “参数值组合”。
    • 作用:批量生成测试用例,列表里每一个元组,都会对应一条测试用例~ 比如:
      • 第 1 组:data 是 {"username": ""}(用户名空),预期 code=-1msg="username 不能为空"
      • 第 2 组:data 是 {"password_confirm": "2"}(密码不一致),预期 code=-2msg="两次密码输入不一致"
      • 第 3 组:data 是 {"username": "test_user_beifan"}(合法数据),预期 code=0msg="注册成功"
  • def test_register_post(user, client, data, code, msg):

    • 测试用例函数,参数里:
      • user:就是图 1 里的 user fixture,会自动传入 “测试用户”(如果需要的话~)
      • client:Django 测试客户端(图 1 里讲过的 “虚拟小浏览器”)
      • data, code, msg:来自 @pytest.mark.parametrize 的参数,每组数据都会跑一次测试~
  • resp = client.post(...)

    • 用 client(虚拟小浏览器)发一个 POST 请求 到 /accounts/register(注册接口),还带了 data(请求体)和 content_type="application/json"(告诉服务器,我发的是 JSON 数据哟~)
  • html = resp.content.decode() → resp_json = json.loads(html)

    • 把响应的二进制内容(resp.content)解码成字符串(html),再转成 JSON(resp_json),方便断言~
  • assert resp_json["code"] == code → assert resp_json["msg"] == msg

    • 检查响应的 code 和 msg 是否符合预期~ 比如:
      • 用户名空时,code 应该是 -1msg 是 username 不能为空
      • 注册成功时,code 是 0msg 是 注册成功

 

🌟 数据库断言 —— 注册成功后,用户真的 “入库” 了吗?

这部分是测试 “注册成功后,数据库用户数量是否变化”,保证代码真的把用户数据存到数据库啦~

def test_register_post(user, client, data, code, msg):  # 1. 发请求前,先查数据库用户数量  user_list = list(User.objects.all())  user_count = len(user_list)  assert user_count == 1  # 假设测试前只有 1 个用户(图 1 里的 test_user)  # 2. 发 POST 请求测试注册  resp = client.post(...)  # (和之前一样,发请求、解析响应)  # 3. 断言响应是否符合预期(code、msg)  assert resp_json["code"] == code  assert resp_json["msg"] == msg  # 4. 如果注册成功(code == 0),再查数据库用户数量  if code == 0:  user_list = list(User.objects.all())  user_count = len(user_list)  assert user_count == 2  # 注册成功后,应该新增 1 个用户 → 总数 2  
逐行拆解
  • user_list = list(User.objects.all()) → user_count = len(user_list)

    • 发请求,先查数据库里的所有用户,数一下有多少个(user_count)。
    • 假设测试环境里,一开始只有图 1 里创建的 test_user,所以 user_count == 1
  • assert user_count == 1

    • 确保测试前数据库状态 “干净”,只有 1 个测试用户,避免其他数据干扰测试结果~
  • if code == 0:

    • code == 0 代表 “注册成功”,这时需要再查数据库,确认用户真的新增了!
  • user_list = list(User.objects.all()) → user_count = len(user_list)

    • 发请求,再次查数据库用户数量。
  • assert user_count == 2

    • 注册成功的话,用户数量应该从 1 变成 2(原来的 test_user + 新注册的用户)。
    • 相当于:“嘿,数据库~ 注册成功后,用户是不是真的存进来啦?数量对不对呀?”

 

🌈 整体流程总结

  1. 造用户:用 @pytest.fixture 提前在数据库造一个 test_user,当 “测试种子”。
  2. 批量测注册:用 @pytest.mark.parametrize 批量测试各种注册场景(用户名空、密码错、注册成功)。
  3. 发请求:用 client.post 模拟浏览器发注册请求,看服务器咋响应。
  4. 断言响应:检查返回的 code 和 msg 是否符合预期(比如注册成功时 code=0)。
  5. 数据库校验:注册成功后,再查数据库用户数量,确保真的新增了用户~

user 固件也就是说意义在于数据库的初始化,管理 验证是否用户名重复

1. 🛠️ 帮数据库 “热热身”

user fixture 里的 User.objects.create_user(...) 一执行,就像给数据库发了条消息:“喂~ 准备好啦,要开始测试咯!”
Django 会因此自动完成数据库连接、创建测试表等一系列准备工作,避免测试时出现 “数据库还没启动” 的尴尬错误~ 就像玩游戏前先加载地图,不然点 “开始” 会卡住呀!

 

2. 🆚 提供 “参照物” 方便验证

比如测试 “用户名不能重复” 时,user 就像一个 “标杆用户”🆔:

  • 它的用户名是 test_user,已经存在于数据库里(先建一个user数据,所以后面的断言是1->2)
  • 当你用同样的用户名 test_user 去注册时,就能验证系统会不会报错 “用户名已存在”
  • 如果没有这个 “参照物”,数据库空空如也,根本测不出 “重复注册” 的逻辑对不对呀~

所以哪怕 user 没在代码里被直接 “点名”,它也是测试里的 “幕后功臣”🌟:既让数据库准备好工作,又提供了关键的 “对比数据”,保证各种注册场景都能被准确测试到~

 

Django 测试中通过 user fixture 自动完成数据库连接的过程

 

🌱 第一步:pytest-django 的 “数据库开关”

user fixture 里有 User.objects.create_user(...) 这行代码 —— 它要往数据库里写数据,这就像给 pytest-django 递了一张 “需要数据库” 的门票🎫。

pytest-django 看到这张 “门票” 后,会自动触发一个核心机制:启用数据库连接
(如果测试里完全用不到数据库操作,pytest-django 会默认 “关闭” 数据库,让测试跑得更快~)

 

🛠️ 第二步:创建 “临时测试数据库”

为了不污染你的真实数据库(比如开发环境的 db.sqlite3),pytest-django 会偷偷做一件事:
自动创建一个全新的临时数据库(名字通常是 test_你的数据库名,比如 test_myproject)。

这个临时数据库就像一个 “一次性舞台”:

  • 结构和你的真实数据库一模一样(表、字段都照着抄)
  • 但里面的数据是干净的,专门给测试用
  • 测试结束后会自动删除,不会留下任何痕迹~

 

🔗 第三步:自动连接到临时数据库

Django 的核心配置里有 DATABASES 选项(在 settings.py 里),比如:

DATABASES = {  'default': {  'ENGINE': 'django.db.backends.sqlite3',  'NAME': BASE_DIR / 'db.sqlite3',  # 真实数据库  }  
}  

当 pytest-django 检测到需要数据库时,会自动 “替换” 这个配置:
把 NAME 改成临时数据库的路径(比如 test_db.sqlite3),然后调用 Django 内置的 connection 模块,建立和这个临时数据库的连接。

这一步就像:
你本来要去 “正式餐厅”(真实数据库),但测试时被悄悄引导到了 “隔壁的临时分店”(临时数据库),地址变了,但进门的方式(连接方式)完全一样~

 

🧹 第四步:自动执行数据库迁移

连接好临时数据库后,pytest-django 还会自动做一件事:
运行所有 migrations(数据迁移文件),确保临时数据库的表结构和你的项目代码完全同步。

就像:
临时舞台搭好了,但还得按设计图(migrations 文件)摆好桌椅(数据表),演员(测试数据)才能上场~

 

🌟 总结:user fixture 触发的 “全自动流程”

  1. user fixture 里的 User.objects.create_user() 触发 “需要数据库” 的信号
  2. pytest-django 接收到信号,创建临时数据库
  3. 自动修改数据库配置,连接到临时数据库
  4. 自动运行迁移,确保表结构正确
  5. 执行 create_user,往临时数据库里写入测试用户数据

整个过程完全自动,不需要你手动写 connect() 或 create_database() 之类的代码~ 就像点外卖时,平台自动帮你完成 “找餐厅、下单、配送”,你只需要等着吃(写测试)就行啦! 😋

 

为什么resp = client.post(...) 就能把提交的data放到数据库里呢

🌠 第一步:client.post(...) 是 “发件人”

🛣️ 第二步:Django 路由 “指路”

🏭 第三步:视图函数 “处理包裹”

register_view 视图函数会打开包裹(data),做一系列操作:

  1. 检查数据:比如看看用户名是不是空的、密码够不够长(就像快递员检查包裹是否违禁品)
  2. 创建用户:如果数据没问题,就会调用 User.objects.create_user(...)(Django 的 ORM 方法),把 data 里的用户名、密码等信息 “翻译” 成数据库能懂的语言(SQL 语句)。

📦 第四步:ORM 当 “翻译官”,把数据存进数据库

Django 的 ORM(对象关系映射)是个超厉害的 “翻译官”:

  • 你写的 User.objects.create_user(username="小明"),它会自动翻译成 SQL 语句:
    INSERT INTO auth_user (username, password) VALUES ('小明', '加密后的密码')
  • 然后通过之前 user fixture 已经建好的数据库连接,把这条 SQL 发给临时数据库执行。

数据库收到指令后,就会在 auth_user 表(用户表)里新增一行记录 —— 你的 data 就这样成功 “住进” 数据库啦!

 

那没有user这个固件了 直接resp = client.post(...) 能不能连接上数据库

哈哈,这个问题就像在问:“如果没有提前打开厨房门,能直接炒菜吗?” 答案是 ——大部分情况会失败!用超萌的例子解释:

假设 user fixture 是 “提前打开厨房门的人”👩🍳,而 client.post(...) 是 “炒菜的动作”:

 

🍳 情况 1:如果你的 post 请求需要操作数据库(比如注册用户)

  • 这时候必须先有 “可用的厨房”(数据库连接),否则炒不了菜~
  • 没有 user fixture,pytest-django 可能会 “偷懒” 不初始化数据库(因为没收到 “需要数据库” 的信号)。
  • 当 client.post(...) 触发视图函数去写数据库时,会发现 “厨房门没开”(数据库没连接),直接报错:DatabaseError 或 “表不存在” 之类的错误~

就像没开煤气就想炒菜,锅是冷的,根本炒不熟呀!

 

🍳 情况 2:如果你的 post 请求完全不碰数据库(比如只是返回固定文本)

  • 比如视图函数只是返回 {"code":0},不读写数据库,那就算没有 user fixture,client.post(...) 也能正常运行~
  • 这就像 “凉拌菜”,不需要开火(数据库),直接拌一拌就能吃~

 

📌 关键结论

client.post(...) 本身不会主动触发数据库连接,它只是发请求的 “快递员”。
是否能连接数据库,取决于测试中有没有其他触发数据库初始化的操作(比如 user fixture 里的 User.objects.create_user)。

如果你的 post 请求需要操作数据库,最好还是带上 user fixture 或其他 “数据库触发器”(比如 django_db fixture),确保 “厨房门是开着的” 哦~ 🔑

 

可是resp = client.post(...) 的后端视图处理不是有创建User.objects.create_user的代码吗 为啥不能执行到这里的时候开始初始化数据库

这个问题超棒!就像在问:“既然炒菜时会用到煤气,为啥不能在炒菜时再开煤气呢?” 这里藏着一个 “先后顺序” 的小秘密~ 

 

🔥 核心原因:“煤气”(数据库连接)必须在 “点火”(执行代码)前打开

Django 测试中,数据库初始化(连接、创建临时表等)是 **“提前准备工作”,必须在任何数据库操作代码(比如 User.objects.create_user)执行之前 ** 完成。

而 client.post(...) 触发的视图函数里的 create_user,属于 “测试过程中才会执行的代码”—— 就像 “点火炒菜” 这个动作,必须在 “煤气已经打开” 之后才能进行。

 

🍳 具体流程对比:

有 user fixture 时:
  1. 测试开始前user fixture 先执行 User.objects.create_user → 触发数据库初始化(开煤气)
  2. 测试进行中client.post(...) 触发视图函数 → 执行 create_user(点火炒菜)→ 顺利执行(煤气已开)
没有 user fixture 时:
  1. 测试开始前:没有任何数据库操作 → pytest-django 认为 “不需要数据库”→ 不初始化(没开煤气)
  2. 测试进行中client.post(...) 触发视图函数 → 执行 create_user(想点火炒菜)→ 发现 “煤气没开”(数据库未初始化)→ 报错!

 

🛠️ pytest-django 的 “小规矩”:

pytest-django 有个 “懒加载” 原则:只有在测试开始前,检测到 “明确需要数据库” 的信号(比如 fixture 里有数据库操作),才会提前初始化数据库

而视图函数里的 create_user 是 “测试运行到一半才执行的代码”,这时候再想初始化数据库已经太晚了 —— 就像炒菜炒到一半才发现没开煤气,火根本点不着呀!

 

🌟 解决办法:给测试 “明确开煤气”

如果不想用 user fixture,也可以用 pytest-django 提供的 django_db fixture,直接告诉 pytest:“我要用到数据库,麻烦提前准备好哦~”

# 不用 user fixture,改用 django_db  fixture  
def test_register_post(client, django_db, data, code, msg):  resp = client.post("/accounts/register", data=data)  # 此时数据库已提前初始化  # ... 后续断言 ...  

django_db 就像一个 “备用煤气开关”,专门负责在测试前打开数据库连接~

可是不做单元测试 我只做开发的话视图User.objects.create_user前也没有什么启动数据库的操作啊

在实际开发中,情况和测试环境完全不同!就像 “家里做饭” 和 “野外露营做饭” 的区别 —— 家里的煤气灶是长期打开、随时可用的,而露营时需要提前手动生火~

 

🏠 开发环境中,数据库连接是 “自动提前就绪” 的

在开发阶段,当你启动 Django 项目(比如 python manage.py runserver)时,Django 会自动完成一系列 “初始化工作”,其中就包括数据库连接的建立,根本不需要你手动写代码 “启动数据库”。

具体来说,Django 会:

  1. 读取 settings.py 里的数据库配置(DATABASES 字典),比如数据库类型(MySQL/PostgreSQL)、地址、用户名密码等。
  2. 启动时自动创建数据库连接池(保持和数据库的 “长期通话” 状态)。
  3. 检查数据库表结构(如果用了 migrate 迁移),确保表已经存在。

这就像你家里的煤气灶,只要插上电、打开总开关,随时拧旋钮就能点火 ——数据库连接在项目启动时就已经 “待命” 了

 

🚀 所以视图里的 User.objects.create_user 能直接执行

当用户在浏览器里提交表单(或者你用 Postman 发请求),触发视图函数里的 User.objects.create_user 时:

  • Django 已经通过启动时建立的数据库连接,把 ORM 代码(create_user)翻译成 SQL。
  • 直接通过现成的连接发给数据库执行,根本不需要 “临时启动数据库”。

这和测试环境的区别在于:

  • 开发环境:项目启动时强制初始化数据库连接(因为 runserver 命令默认需要数据库支持)。
  • 测试环境(pytest):为了效率,默认不初始化数据库,只有明确告诉它 “要用数据库”(比如用 django_db fixture),才会提前准备。

 

📌 总结:开发时 “无需手动启动” 的核心原因

Django 的 runserver 命令在启动项目时,会自动根据 settings.py 的配置完成数据库连接初始化,相当于 “项目一启动,数据库就处于‘开机待命’状态”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/917476.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/917476.shtml
英文地址,请注明出处:http://en.pswp.cn/news/917476.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE-第二季-01

目录 1.Vue程序初体验 1.1 下载并安装vue.js 1.2 第一个Vue程序 1.3 Vue的data配置项 1.4 Vue的template配置项 1.5 Vue实例 和 容器 的关系是&#xff1a;一夫一妻制 2.Vue核心技术 2.0 Vue的模板语法 2.0.1 插值语法 插值语法总结&#xff1a; 2.0.2 指令语法 指…

Android 15 中禁用/启用应用的系统级方法

在 Android 15 的开发中,有时我们需要以系统级权限来控制应用的启用状态。本文将介绍如何使用 PackageManager 来实现应用的禁用和启用功能。 核心方法 在 Android 15 代码中,可以使用以下方法来禁用或启用应用: packageManager.setApplicationEnabledSetting(pkg,Packag…

2025网络工程师技能图谱(附思维导图)

------------比较全面&#xff0c;供学习参考路线图。-----------------------

【ROS2】rclcpp::Node 常用 API

ROS 系列学习教程(总目录) ROS2 系列学习教程(总目录) 目录1. 构造函数2. 节点名称相关3. 获取log对象句柄4. 回调组相关5. Topic发布与订阅6. Service服务端与客户端1. 构造函数 public:Node(const std::string & node_name, const NodeOptions & options NodeOptio…

自动驾驶:技术、应用与未来展望——从开创到全面革新交通出行

一、引言1.1 研究背景与意义在过去的几十年里&#xff0c;随着科技的飞速发展&#xff0c;自动驾驶技术逐渐从科幻小说中的概念走进了现实生活。从最初简单的辅助驾驶功能&#xff0c;到如今高度自动化的自动驾驶系统&#xff0c;这一领域的进步正深刻地改变着我们的出行方式和…

【gradle】插件那些事

文章目录 1. 前言 2. 插件相关介绍 2.1 gradle插件的apply 2.2 引入自定义插件 2.3 常见构建任务 2.4 gradle生命周期 2.5 gradle的惰性属性&可注入的服务 2.6 常见命令 检查依赖树 查看tasks 构建扫描 查看多项目构建的结构 显示所选项目的构建脚本依赖项 指定控制台模式来…

测试平台如何重塑CI/CD流程中的质量协作新范式

测试平台如何重塑CI/CD流程中的质量协作新范式 在DevOps革命席卷全球软件行业的今天&#xff0c;测试的角色正在经历前所未有的转变。传统的"测试最后"模式正在被"测试全程"的新理念所取代&#xff0c;这一转变背后是测试平台与CI/CD流程深度融合带来的质量…

node.js不同环境安装配置

node.js不同环境安装配置 Windows环境安装配置 一、Node.js是什么&#xff1f; ​ Node.js是一个基于Chrome V8引擎的[JavaScript运行环境]。 Node.js使用了一个事件驱动、非阻塞式I/O 的模型&#xff0c;Node.js是一个让JavaScript运行在服务端的开发平台&#xff0c;它让J…

深度学习-读写模型网络文件

模型网络文件是深度学习模型的存储形式&#xff0c;保存了模型的架构、参数等信息。读写模型网络文件是深度学习流程中的关键环节&#xff0c;方便模型的训练、测试、部署与共享。1. 主流框架读写方法&#xff08;一&#xff09;TensorFlow保存模型可以使用 tf.saved_model.sav…

智慧能源管理平台的多层协同控制架构研究

摘要&#xff1a;针对微电网多源异构设备协同难题&#xff0c;提出一种“云-边-端”三层智慧能源管理架构。平台集成数据采集、策略优化与全景分析功能&#xff0c;支持光伏、储能、充电桩等设备的动态调度&#xff0c;通过自适应算法实现防逆流、需量控制及峰谷套利等策略组合…

MySQL面试题及详细答案 155道(021-040)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

2025年IntelliJ IDEA最新下载、安装教程,附详细图文

文章目录下载与安装IDEA大家好&#xff0c;今天为大家带来的是IntelliJ IDEA的下载、安装教程&#xff0c;亲测可用&#xff0c;喜欢的朋友可以点赞收藏哦下载与安装IDEA 首先先到官网下载最新版的IntelliJ IDEA, 下载后傻瓜式安装就好了 1、下载完后在本地找到该文件&#xf…

深入解析 Apache Tomcat 配置文件

前言 Apache Tomcat 作为最流行的开源 Java Web 应用服务器之一&#xff0c;其强大功能的背后离不开一系列精心设计的配置文件。正确理解和配置这些文件&#xff0c;是部署、管理和优化 Web 应用的关键。本篇博客将深入探讨 Tomcat 的核心配置文件&#xff0c;涵盖其结构、关键…

ThinkPHP8学习篇(一):安装与配置

ThinkPHP有非常多的功能库&#xff0c;我的学习策略很明确&#xff1a;不贪多求全&#xff0c;只掌握最核心的20%功能&#xff0c;解决80%的业务需求。所有学习都围绕一个目标&#xff1a;够用就行。遇到复杂问题时&#xff0c;再具体学习对应的内容。 作为ThinkPHP学习的第一…

【Python练习】075. 编写一个函数,实现简单的语音识别功能

075. 编写一个函数,实现简单的语音识别功能 075. 编写一个函数,实现简单的语音识别功能 安装依赖库 示例代码 代码说明 示例输出 注意事项 使用 PocketSphinx 进行离线语音识别 注意事项 实现方法 使用SpeechRecognition库实现语音识别 使用PyAudio和深度学习模型 使用Vosk离…

chrome的数据采集插件chat4data的使用

简介&#xff1a; Chat4Data是一款Chrome扩展插件&#xff0c;支持AI网页数据采集与分析。用户可通过Chrome应用商店安装后&#xff0c;在网页上选择区块和字段进行数据抓取&#xff0c;设置采集页数后导出结果。该工具适用于结构化数据提取&#xff0c;操作简便&#xff0c;为…

《人形机器人的觉醒:技术革命与碳基未来》——类人关节设计:人工肌肉研发进展及一款超生物肌肉Hypermusclet的设计与制造

目录&#xff1a;一、人工股肉的不同种类及工作原理和比较优势二、人工肌肉研发的重点难点及成果进展和趋势三、人工肌肉主要研发机构及其研发成果四、人工肌肉主要性能检测表征能力及标准体系建设五、人工肌肉主要制造商及其产品性能优势和供应能力六、人工肌肉在机器人市场应…

【人工智能】AI代理的伦理迷局:自主智能体的责任归属之谜

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在人工智能时代,AI代理作为自主决策的代表,正深刻改变着人类社会。然而,其伦理困境日益凸显:当AI代理做出自主决策时,谁应为其后果负责…

C语言数据结构(6)贪吃蛇项目1.贪吃蛇项目介绍

1. 游戏背景 贪吃蛇是久负盛名的游戏&#xff0c;它也和俄罗斯方块&#xff0c;扫雷等游戏位列经典游戏的行列。 在编程语言的教学中&#xff0c;我们以贪吃蛇为例&#xff0c;从设计到代码实现来提升学生的编程能力和逻辑能力。 2. 游戏效果演示 3. 项目目标 使用C语言…

神经网络的并行计算与加速技术

神经网络的并行计算与加速技术一、引言随着人工智能技术的飞速发展&#xff0c;神经网络在众多领域展现出了巨大的潜力和广泛的应用前景。然而&#xff0c;神经网络模型的复杂度和规模也在不断增加&#xff0c;这使得传统的串行计算方式面临着巨大的挑战&#xff0c;如计算速度…