Django单元测试实战:从模型到API的完整测试指南
写代码不写测试就像开车不系安全带——平时没感觉出事就是大事。我之前带过不少新人一说“给Django项目补单元测试”第一反应都是“不会写”“不知道怎么下手”。其实Django自带一套相当完整的测试工具链难度比你想的低很多。这篇就把我这些年写Django单元测试的整套思路、常用套路和踩过的坑一次说清楚。1. 先搞明白Django单元测试到底测什么1.1 核心需求解析先说个扎心的事实很多人写的“单元测试”其实根本不是单元测试而是集成测试。比如测一个视图它连数据库、走路由、渲染模板、查缓存全链路都跑了一遍——这种测试当然有价值但它属于集成测试跑起来慢出了问题也不容易定位。Django里真正的单元测试核心是测逻辑本身而不是测框架。你需要问自己的是这个函数的输入输出对不对这个模型的自定义方法返回什么结果这个视图在特定请求下返回什么状态码这个序列化器对边界数据的处理是否合理Django官方推荐的测试方式是“以TestCase为基础自上而下做集成式单元测试”——我个人的实践是把Django的TestCase当作隔离的运行环境在里面跑你的代码逻辑关注点始终放在“你的逻辑是否正确”而不是“框架是否正常工作”。1.2 Django测试框架的设计逻辑Django的测试框架底层还是Python标准库的unittest在此基础上额外提供了这些关键能力测试数据库自动创建与销毁每次跑测试Django会单独建一个测试数据库测完直接干掉不碰你的开发数据和生产数据测试客户端一个模拟HTTP请求的客户端直接调你项目的URL路由省去起服务器TestCase类增强在unittest.TestCase基础上增加了数据库事务包裹、缓存清理、文件存储隔离等能力Fixture加载机制可以自动加载JSON/YAML格式的初始数据举一个最简单的例子Django中的测试代码是这样组织的from django.test import TestCase from myapp.models import Article class ArticleModelTests(TestCase): def test_article_slug_generation(self): article Article(titleHello World) self.assertEqual(article.slug, hello-world)这里用到的不是普通函数而是继承了django.test.TestCase的类。它自动给每个测试方法开启一个数据库事务测试结束自动回滚数据互不干扰——这是Django测试框架最核心的设计思路之一隔离。为什么要隔离因为测试必须可重复。你今天跑通过明天换台机器跑也应该通过你跑你的我跑我的互不影响。这个“隔离”在设计里无处不在后面你看到TestCase、TransactionTestCase、APITestCase这些类本质上都是在不同隔离级别上做文章。2. 搭好测试环境的3个关键准备2.1 测试数据库配置Django跑测试时默认会创建一个名为test_你的数据库名的库比如你的数据库叫myblog_dev测试库就是myblog_test_dev。大多数情况下你什么都不用配直接跑就行。但有几个场景需要显式处理场景一使用SQLite做本地开发想直接跑内存库DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, TEST: { NAME: :memory:, }, } }跑测试时用内存SQLite会让速度飙升但要注意内存库要求每个连接访问同一块内存如果你用了额外的连接配置比如CONN_MAX_AGE、多线程可能报no such table之类的问题。保险起见我用内存库时会顺手把CONN_MAX_AGE置0。场景二测试库命名冲突如果CI流水线上多个任务共享同一个数据库服务可以在TEST配置里改名字DATABASES { default: { ENGINE: django.db.backends.postgresql, NAME: myapp_prod, USER: myuser, PASSWORD: secret, HOST: localhost, PORT: 5432, TEST: { NAME: test_myapp_ci, }, } }2.2 创建测试用的独立配置文件这是很多项目忽略的细节。如果直接把测试配置和生产配置混在一起非常容易出事故。我见过有人把生产数据库的账号密码写进测试配置一旦同事误跑测试整个开发库都被“测试数据”给清了。我的习惯是单独建一个settings_test.pyfrom .settings import * # noqa: F403 DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: :memory:, } } PASSWORD_HASHERS [ django.contrib.auth.hashers.MD5PasswordHasher, ] EMAIL_BACKEND django.core.mail.backends.locmem.LocMemBackend DEBUG False然后跑测试时用--settings参数指定python manage.py test myapp.tests --settingsmyproject.settings_test这个小习惯至少帮我避开了三类坑测试库误连生产库、密码哈希太慢、测试时真实发邮件。2.3 测试文件的组织方式在Django里测试代码通常放在每个app下的tests.py里但项目越来越大之后我更建议拆成包结构myapp/ __init__.py tests/ __init__.py test_models.py test_views.py test_serializers.py test_forms.py test_apis.py test_commands.py这样命名的好处是只跑某一类测试非常方便——# 只跑模型的测试 python manage.py test myapp.tests.test_models # 只跑APIs的测试 python manage.py test myapp.tests.test_apis尤其当测试文件超过300行单文件会变得很难维护。拆包之后每个文件职责单一定位问题也快。3. 从零到一编写第一个Django单元测试3.1 模型层的测试写法模型层测试是最容易上手的核心思路是创建实例、调用方法、断言结果。假设我们有一个图书模型class Book(models.Model): title models.CharField(max_length200) author models.CharField(max_length100) price models.DecimalField(max_digits6, decimal_places2) published_date models.DateField() is_bestseller models.BooleanField(defaultFalse) def years_since_published(self, current_date): delta current_date - self.published_date return max(delta.days // 365, 1) def apply_discount(self, percent): if not 0 percent 100: raise ValueError(折扣百分比必须在0到100之间) self.price self.price * (1 - percent / 100) self.save()对应测试from datetime import date from django.test import TestCase from myapp.models import Book class BookModelTests(TestCase): def setUp(self): self.book Book.objects.create( titlePython进阶之路, author某开发者, price68.00, published_datedate(2022, 5, 10), ) def test_years_since_published_computes_correctly(self): current date(2024, 5, 10) result self.book.years_since_published(current) self.assertEqual(result, 2) def test_apply_discount_updates_price(self): self.book.apply_discount(20) self.assertEqual(float(self.book.price), 54.40) def test_apply_discount_rejects_invalid_percent(self): with self.assertRaises(ValueError): self.book.apply_discount(150)关于这个测试有几个细节值得讲setUp和setUpTestData的选择。上面用了setUp每个测试方法跑之前都会创建一次Book对象。如果测试类里方法很多每次都建对象也是开销。如果数据只读不修改可以改用setUpTestDataclass BookModelTests(TestCase): classmethod def setUpTestData(cls): cls.book Book.objects.create(...)setUpTestData在整个测试类运行期间只执行一次创建的对象在类级别的测试方法之间共享速度非常快。但有个前提测试方法里不能修改这个对象否则会影响其他测试方法。我的经验法是只读数据的准备用setUpTestData每个测试需要独特数据的场景用setUp3.2 视图与请求响应的测试模型没问题了下一步就到视图层。Django的Client对象可以直接发起GET/POST请求而不用真的去启动一个开发服务器。看一个简单案例测“文章列表”视图from django.test import TestCase from django.urls import reverse from myapp.models import Article class ArticleViewTests(TestCase): def setUp(self): self.client Client() def test_article_list_returns_200(self): Article.objects.create(title第一篇文章, content内容) response self.client.get(reverse(article-list)) self.assertEqual(response.status_code, 200)这里面有几个关键API你要熟悉self.client.get(url)模拟GET请求self.client.post(url, data)模拟POST提交表单self.client.login(username..., password...)模拟登录前提是测试库里已有该用户self.client.force_login(user)直接在当前会话中强制登录某个用户不需要密码self.client.logout()登出用force_login比login更常用因为省去了创建用户时对密码的处理。创建测试用户时要注意Django默认的密码哈希器PBKDF2很慢几百个测试跑下来会明显变慢可以在测试配置里换掉哈希器——这就是前面提到的PASSWORD_HASHERS [django.contrib.auth.hashers.MD5PasswordHasher]的原因。再来一个带身份认证的测试示例from django.contrib.auth.models import User from django.test import TestCase from django.urls import reverse from myapp.models import Profile class ProfileViewTests(TestCase): classmethod def setUpTestData(cls): cls.user User.objects.create_user( username某开发者, passwordtest-password-123, ) def test_profile_requires_login(self): # 未登录访问应重定向到登录页 response self.client.get(reverse(profile, kwargs{pk: self.user.pk})) self.assertEqual(response.status_code, 302) def test_profile_accessible_when_logged_in(self): self.client.force_login(self.user) response self.client.get(reverse(profile, kwargs{pk: self.user.pk})) self.assertEqual(response.status_code, 200) self.assertContains(response, 某开发者)这个测试同时覆盖了“未登录重定向”和“已登录可访问”两种场景基本覆盖了Web开发里最常见的权限判断逻辑。3.3 表单与序列化器的边界测试表单和序列化器往往是bug高发区因为它们的验证逻辑通常比较复杂。测试它们有一个好处不需要数据库也不用客户端直接实例化、传数据、看errors。Django表单的测试方式from django.test import SimpleTestCase from myapp.forms import RegisterForm class RegisterFormTests(SimpleTestCase): def test_valid_form_saves(self): form RegisterForm(data{ username: 某开发者, email: devexample.com, password1: password-123, password2: password-123, }) self.assertTrue(form.is_valid()) def test_password_mismatch_shows_error(self): form RegisterForm(data{ username: 某开发者, email: devexample.com, password1: password-123, password2: password-456, }) self.assertFalse(form.is_valid()) self.assertIn(password2, form.errors)注意这里用的是SimpleTestCase不需要数据库支持跑完不创建测试库速度比TestCase快不少。只要是纯逻辑测试都应该优先用SimpleTestCase。DRF序列化器的测试也是一样套路from rest_framework.test import APITestCase from myapp.serializers import BookSerializer from myapp.models import Book class BookSerializerTests(APITestCase): def test_serializer_validates_price_greater_than_zero(self): data {title: 测试书名, price: -10} serializer BookSerializer(datadata) self.assertFalse(serializer.is_valid()) self.assertIn(price, serializer.errors)4. 进阶场景接口测试、异步任务与信号4.1 用APITestCase写RESTful接口测试如果你的项目用了DRFDjango REST Framework写API测试首推APITestCase。它自带一个API客户端除了支持get/post/put/patch/delete之外还处理了JSON格式的请求体和响应解析省去很多手动处理。from rest_framework.test import APITestCase from rest_framework import status from django.contrib.auth.models import User from myapp.models import Book class BookAPITests(APITestCase): def setUp(self): self.user User.objects.create_user( username某开发者, passwordtest-password-123, ) self.book Book.objects.create( titlePython进阶之路, author某开发者, price68.00, published_date2022-05-10, ) def test_list_books(self): response self.client.get(/api/books/) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data[count], 1) def test_create_book_requires_auth(self): # 未登录创建应收到401或403 response self.client.post( /api/books/, {title: 新书, price: 39.00, author: 某开发者}, formatjson, ) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) def test_create_book_when_authenticated(self): self.client.force_authenticate(userself.user) response self.client.post( /api/books/, { title: 新书, price: 39.00, author: 某开发者, published_date: 2024-01-01, }, formatjson, ) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(Book.objects.count(), 2)写API测试时我最常跟新人说的一句话是不光测成功路径更要测失败路径。上面的test_create_book_requires_auth就是典型的失败路径测试。一个接口的权限控制做没做对往往就靠这种用例兜住。4.2 测试信号处理器和Celery异步任务项目里用post_save信号去同步搜索索引、统计计数这类需求很常见。信号处理器写完之后有一个让人头疼的问题在测试环境里它一样会触发。比如创建用户时信号里连带创建一份UserProfile。如果你在测试里只关心User的创建信号带来的额外数据库操作就是干扰。这时候可以用django.test.utils.override的signal断开方法或者用django.db.models.signals的receiver临时断开。常见做法是from django.test import TestCase from django.db.models.signals import post_save from unittest.mock import patch from myapp.models import User class UserSignalTests(TestCase): patch(myapp.signals.create_profile_on_user_saved) def test_user_creation_triggers_profile_signal(self, mock_create_profile): User.objects.create_user(username某开发者, passwordpass) self.assertTrue(mock_create_profile.called)用patch替代真实信号逻辑既验证了“信号被调用”这个事实又避免了信号里额外逻辑影响测试。这是我在测试环境里处理信号的固定套路。Celery异步任务的测试和信号类似测试环境里任务默认是同步执行的但如果你在配置里把一个任务命令设成异步测起来会等不到结果。推荐的方式是配合CELERY_TASK_ALWAYS_EAGER True# settings_test.py CELERY_TASK_ALWAYS_EAGER True CELERY_TASK_EAGER_PROPAGATES True加上之后所有的delay()、apply_async()调用都会同步立刻执行测试里可以直接断言执行结果。如果没有加这个你需要在测试里mocker.patch掉任务方法或者把任务调用改成同步调用非常烦人——这是很多人踩过坑、找半天原因才发现是Celery配置问题的地方。4.3 文件上传与媒体文件测试测试文件上传场景时Django会真的把文件写到MEDIA_ROOT目录这会让测试互相污染。解决方法是在测试配置里把媒体目录指向临时目录MEDIA_ROOT os.path.join(BASE_DIR, tmp_test_media)或者更优雅一点用override_settings在类或者方法级别临时覆盖from django.test import TestCase, override_settings from django.core.files.uploadedfile import SimpleUploadedFile class AvatarUploadTests(TestCase): override_settings(MEDIA_ROOTtempfile.gettempdir()) def test_upload_file(self): upload_file SimpleUploadedFile( avatar.jpg, bfile_content, content_typeimage/jpeg, ) response self.client.post(/upload-avatar/, {file: upload_file}) self.assertEqual(response.status_code, 200)5. 测试运行提速与总结的套件配置5.1 只跑部分测试的命令项目大了之后最痛苦的往往不是写测试而是跑测试太慢。我有几招提速的经验实测下来非常有效第一招只跑当前改动相关的测试python manage.py test myapp.tests.test_apis.BookAPITests这个命令只跑BookAPITests类里的方法秒级完成适合开发时快速验证。第二招并行跑测试Django从1.9开始支持并行测试通过--parallel参数指定进程数python manage.py test --parallel4注意两点一是数据库的配置要支持并发连接SQLite内存库在并行下会出问题建议用PostgreSQL或MySQL二是你的测试之间必须真正隔离如果测试代码里写死了某些固定ID或全局变量并行跑起来会互相踩。第三招用pytest替代manage.py test我在几个大型项目里都切换到pytest pytest-django原因有两点测试fixture复用更自然不需要每个类都写setUp用函数式fixture就能共享数据代码量降一半失败时console输出的变量信息比unittest详细很多直接把具体的assert差值打印出来定位问题快一个最简单的pytest-django例子import pytest pytest.mark.django_db def test_book_price_discount(): book Book.objects.create(title测试, price80) book.apply_discount(50) assert float(book.price) 40注意这里必须加pytest.mark.django_db装饰器否则pytest不会给你测试数据库环境。5.2 测试覆盖率统计想清楚哪些代码没覆盖到建议加上coverage.py。安装后直接跑coverage run --source. manage.py test myapp coverage report --skip-covered输出到你眼前的是每个文件的覆盖率百分比。我的原则是核心业务逻辑价格计算、权限判断、状态流转覆盖率必须到90%以上视图层、序列化器尽量到80%模板文件本身不用刻意追求覆盖率模板的展示逻辑靠手工回归就够了覆盖率数字不是KPI但能帮你看清楚团队测试投入的方向有没有跑偏。有几次我扫覆盖率发现模型层光秃秃一片全在测视图这明显是测试重点放错了地方。5.3 自定义测试命令的统一入口我更推荐在项目根目录放一个runtests.py脚本把测试入口固定下来#!/usr/bin/env python import os import sys import django from django.test.utils import get_runner from django.conf import settings if __name__ __main__: os.environ[DJANGO_SETTINGS_MODULE] myproject.settings_test django.setup() TestRunner get_runner(settings) test_runner TestRunner(verbosity2, parallel2) failures test_runner.run_tests([myapp]) sys.exit(bool(failures))这样无论是本地开发、CI流水线还是同事接手拿到项目后一条命令就能跑测试不需要看文档里那一长串的路径参数。6. 常见问题与排查技巧实录6.1 测试数据库创建失败的排查现象跑测试报错Got an error creating the test database: permission denied to create database原因当前数据库用户没有建库权限。Django跑测试时会自动创建test_xxx数据库必须要有CREATE DATABASE权限。解决给用户授CREATE权限或者让DBA把测试库提前建好在TEST配置里指定TEST: { NAME: test_myapp, CREATE: False, }6.2 测试数据残留与状态污染现象单跑某个测试类通过整个测试套件跑就失败。这是典型的测试间数据耦合。常见起因是某个测试直接操作了self.test外的全局状态比如往缓存里写了key其他测试读到这个脏数据修改了某个类变量其他测试以为这是原始值在setUpTestData里创建的对象被某个测试方法给改了我的排查顺序先看有没有修改类级共享对象的测试方法再查缓存读写最后查是否有未清理的Mock或patch6.3 测试里创建的User无法登录现象用create_user创建了用户但login()返回False。原因测试环境里用了快速哈希器比如MD5PasswordHasher而表单登录校验时密码哈希过程不一致或者你直接用create()而不是create_user创建用户导致密码字段被明文写入没经过哈希。解决创建测试用户一律用create_user别用create然后调用force_login跳过密码验证user User.objects.create_user(usernametester, passwordplain-password) self.client.force_login(user)6.4 JSON响应断言太繁琐DAFAPI测试里经常需要校验响应JSON里某些字段但不关心其他字段。我写了一个小工具函数避免重复from django.test import TestCase class ExtendedTestCase(TestCase): def assertJSONSubset(self, response_json, expected): 断言expected中的所有字段都出现在response_json中 for key, value in expected.items(): self.assertIn(key, response_json, f缺少字段: {key}) self.assertEqual(response_json[key], value)让所有API测试继承这个类断言的代码量能少一半可读性也强很多。6.5 外部HTTP请求导致测试变慢或挂起如果被测代码里存在真实的第三方HTTP请求调用跑测试时大概率会出问题——网络不通就失败网络通了又很慢。我的做法是强制Mock掉所有出站HTTP请求import responses responses.activate def test_fetch_external_data(self): responses.add( responses.GET, https://api.example.com/v1/data, json{status: ok}, status200, ) # 调用被测代码 result fetch_external_data() self.assertEqual(result[status], ok)用responses库的好处是测试代码里没注册的外部URL一旦被请求就会直接抛异常防止你偷偷在测试里依赖真实网络。6.6 测试时间相关的代码写时间相关逻辑的测试有个经典坑代码里用datetime.now()或者timezone.now()测试跑太快时期望值和实际值差了几毫秒导致断言失败。解决办法是用freezegun库from freezegun import freeze_time freeze_time(2024-06-01 10:00:00) def test_birthday_reminder(self): # 在这个测试里datetime.now()永远返回2024-06-01 10:00:00 result check_birthday_reminder() self.assertEqual(result, 今天有提醒)有了freeze_time任何时间计算都能精确控制不用再写“宽容差几秒”这种含糊断言。7. 最后的几点编写与落地建议想把单元测试真正用起来不是写一个测试文件就完事关键是建立可持续的测试习惯。我用的流程给出来给你参考写代码前先写测试哪怕是伪代码级别的测试先把期望行为和输入输出定义清楚。这能逼你想清楚接口设计写出来的代码可测性天然高跑全量测试之前先跑局部改动一个小模块先跑那个模块的测试秒级反馈不浪费几分钟等待时间修完bug先补测试每次修复问题问自己“现在补的这个测试能不能防止它再犯”——能就补不能说明用例没写到点子上测试失败先看错误信息别急着改代码先确认是断言失败还是异常抛出是数据问题还是逻辑问题。排查顺序比修复本身更重要关于测试覆盖率我个人的目标线是业务核心模块90%以上整体在80%左右。低于70%基本说明测试是摆设高于95%则容易过度测试——文档结构、字段展示这类东西测了也没多少收益白白加重维护负担。最后分享一个实操技巧把“批量创建数据 批量断言”封装成helper函数全项目统一用。比如SDK项目里大家都要创建产品、用户、订单我写了一个TestDataFactory一行就能搞定一个带依赖关系的测试数据测试代码的重复率一下子就降下来了。写Django单元测试这事门槛真的不高——框架自带能力已经很完整要爬的坡主要是“组织好测试环境”“掌握断言模式”“学会常见场景的测试套路”。跑通一个用例只需要几分钟但换来的是敢重构、能定位、不焦虑。这也是我坚持在每个项目里第一时间搭建测试体系的原因短期看是花时间长期看是省时间。

相关新闻

MATLAB入门教程PPT课件:24学时从零基础到上机实战

MATLAB入门教程PPT课件:24学时从零基础到上机实战

简介:这份MATLAB教程PPT课件面向高校学生、初学者及需要系统梳理MATLAB基础的工程技术人员,帮助其掌握矩阵运算、数据可视化与数值计算等核心技能。压缩包内共1个PPT文件,大小约8.97MB,内容以课堂讲义形式组织,涵盖MAT…

2026/10/17 12:41:00 阅读更多 →
Java实验设计:基于Socket与SQL的档案管理系统实战

Java实验设计:基于Socket与SQL的档案管理系统实战

简介:这份资源是一套面向高校Java课程实验设计的完整源码方案,围绕C/S架构的小型档案管理系统展开,适合正在完成面向对象与多线程综合实验的学生及需要Socket通信实战案例的开发者参考。系统涵盖客户端与服务器端两个子系统,涉及用…

2026/10/17 12:41:00 阅读更多 →
Claude Code 安装教程:Node.js 环境配置与常见报错解决

Claude Code 安装教程:Node.js 环境配置与常见报错解决

1. 为什么 2026 年还要认真折腾一遍 Claude Code1.1 这个工具到底解决什么问题Claude Code 是 Anthropic 推出的命令行 AI 编程助手,它跟网页版聊天最大的区别在于:它能直接读写你本地的项目文件、执行终端命令、跑测试、改代码、提交 Git。说白了&#…

2026/10/17 12:41:00 阅读更多 →

最新新闻

AI时代程序员必看:脱离大模型,你还能独立工作吗?Vibe Coding挑战与应对

AI时代程序员必看:脱离大模型,你还能独立工作吗?Vibe Coding挑战与应对

本文探讨了Vibe Coding(氛围编码)如何借助AI改变编程方式,引发对程序员核心能力的思考。文章指出,AI擅长生成代码,但复杂系统判断、风险识别仍需人类智慧。强调基础知识和底层原理的重要性,提出程序员应驾驭…

2026/10/17 13:45:46 阅读更多 →
2026年企业网盘终极对比:坚果云 vs OneDrive vs Dropbox vs 百度网盘企业版

2026年企业网盘终极对比:坚果云 vs OneDrive vs Dropbox vs 百度网盘企业版

文章目录一、企业网盘选型,为什么不能只看容量和价格?二、测评方法论:15 个维度的统一标尺2.1 测评维度定义2.2 测试环境说明三、四款产品逐一深度测评3.1 坚果云团队版 —— 专业同步盘,技术团队首选🔧 核心技术要点拆…

2026/10/17 13:45:46 阅读更多 →
新手程序员必看:3个实操任务,教你如何高效利用AI大模型提升办公效率

新手程序员必看:3个实操任务,教你如何高效利用AI大模型提升办公效率

本文介绍了如何通过三个具体任务(整理文件、汇总资料、生产公众号文章)来测试和利用AI大模型提高办公效率。文章强调了明确任务需求、设定边界条件以及验证交付物的重要性,并提供了可直接复制的提示词模板。通过这些实操步骤,即使…

2026/10/17 13:45:46 阅读更多 →
普通人也能抓住的AI高薪风口!学会这些技能,薪资翻倍不是梦

普通人也能抓住的AI高薪风口!学会这些技能,薪资翻倍不是梦

AI岗位迎来大爆发,2026年1-7月同比暴涨近8倍,平均月薪破6万。不再是顶尖技术人才专属,运营、文案等普通岗位也能结合AI提效。普通人只需学会借助AI工具优化工作,即可快速提升竞争力,实现薪资翻倍。抓住AI风口&#xff…

2026/10/17 13:45:46 阅读更多 →
C# OpenXml 操作 Word 表格:从基础结构到样式合并的完整指南

C# OpenXml 操作 Word 表格:从基础结构到样式合并的完整指南

简介:面向需要在C#程序中自动化生成Word报表的.NET开发者,这份PDF演示了如何借助OpenXml SDK为Word文档添加表格。内容从引入DocumentFormat.OpenXml命名空间开始,逐步讲解AddTable方法的封装、TableGrid列数定义、表格边框样式设置&#xff…

2026/10/17 13:45:46 阅读更多 →
TPS54201低输入电压hiccup误触发,PNP三极管补偿方案解析

TPS54201低输入电压hiccup误触发,PNP三极管补偿方案解析

简介:面向LED照明系统设计人员,尤其适合熟悉电源管理IC与LED驱动器的工程师,围绕TPS54201宽输入电压(4.5V~28V)1.5A同步降压LED驱动芯片,解决低输入电压下负载LED电流不稳定的问题,并给出实际电…

2026/10/17 13:44:45 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →