django-wiki 0.13.0 常用 CLI 命令与工具详解
django-wiki 0.13.0 CLI 工具体系全实测:manage.py 命令分组与 help 回显、wiki_notifications_create_defaults/notifymail/thumbnail 扩展命令、dumpdata/loaddata 备份恢复、gunicorn 托管与平滑重启、升级命令顺序与常见坑修复实录
django-wiki 0.13.0 常用 CLI 命令与工具详解
目标:系统梳理 django-wiki 0.13.0 部署后可用的全部命令行工具——Django
manage.py中与 wiki 运维直接相关的命令(迁移、账号、备份恢复、通知、缩略图、会话、静态文件)、django-wiki 自带的wiki_notifications_create_defaults、django_nyt 的notifymail、sorl-thumbnail 的thumbnail,以及生产托管用的 gunicorn 命令。所有命令与回显均在 Debian 13 + Python 3.12.16 + django-wiki 0.13.0 + Django 6.0.9 环境实测逐行照抄。
一、环境信息
- 操作系统:Debian 13(trixie)
- Python:3.12.16(虚拟环境
/srv/wiki/venv) - django-wiki:0.13.0(PyPI 包名
wiki);Django:6.0.9;gunicorn:26.2.0 - 工程目录:
/srv/wiki,settings 模块wikisite.settings,数据库 SQLite(/srv/wiki/db.sqlite3) - 服务监听:gunicorn 绑定
0.0.0.0:8000 - 演示账号:超级用户
root/q1w2e3r4 - 下文所有
manage.py命令均在/srv/wiki目录下以./venv/bin/python manage.py ...形式执行
💡 说明:本篇为 CLI 专题篇,不重复安装过程。组件尚未部署的,请先按《Debian 13 安装 django-wiki 0.13.0 指南》完成安装与工程集成;配置参数的语义详见《django-wiki 0.13.0 配置参数详解》。
二、工具概览
django-wiki 没有独立的客户端 CLI,一切运维命令通过 Django 的 manage.py 分发。实测 ./venv/bin/python manage.py help 回显(命令按来源应用分组,逐行照抄):
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[auth]
changepassword
createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
optimizemigration
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver
[django_nyt]
notifymail
[notifications]
wiki_notifications_create_defaults
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver
[thumbnail]
thumbnail
与 django-wiki 运维直接相关的命令与用途:
| 命令 | 来源 | 用途 |
|---|---|---|
migrate / showmigrations / sqlmigrate | django | 建表、迁移状态核对、SQL 审查 |
check / check --deploy | django | 工程自检、生产部署安全检查 |
diffsettings | django | 核对哪些配置真正生效 |
createsuperuser / changepassword | auth | 管理员建号与改密 |
dumpdata / loaddata | django | 文章数据备份与恢复(JSON fixture) |
shell / dbshell | django | 交互式查询文章模型 / 数据库 |
wiki_notifications_create_defaults | wiki notifications 插件 | 为存量文章所有者/编辑者补建订阅 |
notifymail | django_nyt | 投递通知邮件(守护/定时两种模式) |
thumbnail | sorl-thumbnail | 清理图片插件产生的缩略图缓存 |
clearsessions | sessions | 清理过期会话 |
collectstatic | staticfiles | 收集静态文件 |
gunicorn | pip 独立命令 | 生产 WSGI 托管 |
三、前置条件
- 工程已完成
migrate,check无错误:
cd /srv/wiki
./venv/bin/python manage.py check
System check identified no issues (0 silenced).
- 已存在超级用户
root(密码q1w2e3r4); - 通知相关命令要求
INSTALLED_APPS含django_nyt.apps.DjangoNytConfig与wiki.plugins.notifications.apps.NotificationsConfig; thumbnail命令要求INSTALLED_APPS含sorl.thumbnail。
四、各工具详解
4.1 迁移系:migrate / showmigrations / sqlmigrate
showmigrations 核对 wiki 各应用的迁移是否全部落库(可只点名关心的应用,实测回显):
./venv/bin/python manage.py showmigrations wiki wiki_attachments wiki_images wiki_notifications django_nyt
wiki
[X] 0001_initial
[X] 0002_urlpath_moved_to
[X] 0003_mptt_upgrade
wiki_attachments
[X] 0001_initial
[X] 0002_auto_20151118_1816
wiki_images
[X] 0001_initial
[X] 0002_auto_20151118_1811
wiki_notifications
[X] 0001_initial
[X] 0002_auto_20151118_1811
django_nyt
[X] 0001_initial
[X] 0002_notification_settings
[X] 0003_subscription
[X] 0004_notification_subscription
[X] 0005__v_0_9_2
[X] 0006_auto_20141229_1630
[X] 0007_add_modified_and_default_settings
[X] 0008_auto_20161023_1641
[X] 0009_alter_notification_subscription_and_more
[X] 0010_settings_created_settings_modified_and_more
[X] 0011_add_interval_to_disable_email_notifications
[X] 0012_alter_big_auto_field
全部 [X] 即健康;出现 [ ] 说明有迁移未执行,跑一次 migrate 即可。
sqlmigrate 查看迁移将执行的真实 SQL(升级前审查用,实测输出节选):
./venv/bin/python manage.py sqlmigrate wiki 0001
BEGIN;
--
-- Create model Article
--
CREATE TABLE "wiki_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "created" datetime NOT NULL, "modified" datetime NOT NULL, "group_read" bool NOT NULL, "group_write" bool NOT NULL, "other_read" bool NOT NULL, "other_write" bool NOT NULL);
--
-- Create model ArticleForObject
--
CREATE TABLE "wiki_articleforobject" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "object_id" integer unsigned NOT NULL CHECK ("object_id" >= 0), "is_mptt" bool NOT NULL, "article_id" integer NOT NULL REFERENCES "wiki_article" ("id") DEFERRABLE INITIALLY DEFERRED, "content_type_id" integer NOT NULL REFERENCES "django_content_type" ("id") DEFERRABLE INITIALLY DEFERRED);
核心表结构一目了然:wiki_article(权限四字段)+ wiki_articleforobject(与 URLPath 的 contenttypes 桥接)+ wiki_articlerevision(正文、标题、user_message 修订说明、ip_address)等。
4.2 账号系:createsuperuser / changepassword
createsuperuser --noinput(脚本化建号,实测回显):
DJANGO_SUPERUSER_PASSWORD=q1w2e3r4 ./venv/bin/python manage.py createsuperuser --username root --email root@example.com --noinput
Superuser created successfully.
--noinput 跳过全部交互并绕过密码强度校验器,适合批量初始化。
changepassword 交互改密,实测两个坑(详见「六、常见问题」6.1):非 TTY 管道输入会因 getpass 失败抛 EOFError;弱密码会被 AUTH_PASSWORD_VALIDATORS 拦截,实测回显:
This password is too common.
Password: Changing password for user 'root'
Traceback (most recent call last):
File "/usr/local/lib/python3.12/getpass.py", line 69, in unix_getpass
old = termios.tcgetattr(fd) # a copy to save
^^^^^^^^^^^^^^^^^^^^^
termios.error: (25, 'Inappropriate ioctl for device')
(中间 traceback 帧略)
EOFError
参数速查(manage.py changepassword --help 实测节选):位置参数 [username](缺省为当前用户)、--database {default}。
4.3 备份与恢复:dumpdata / loaddata
django-wiki 的文章树、修订历史、权限字段全在 wiki 应用的表里,用 Django fixture 机制做逻辑备份最可靠。
dumpdata 导出(实测命令与回显):
./venv/bin/python manage.py dumpdata wiki --indent 2 -o wiki_backup.json
ls -l wiki_backup.json
head -12 wiki_backup.json
-rw-r--r-- 1 root root 10721 Nov 1 13:22 wiki_backup.json
[
{
"model": "wiki.article",
"pk": 1,
"fields": {
"current_revision": 1,
"created": "2026-11-01T12:13:37.696Z",
"modified": "2026-11-01T12:13:37.725Z",
"owner": null,
"group": null,
"group_read": true,
"group_write": true,
核对备份内容构成:
./venv/bin/python -c "import json,collections; d=json.load(open('wiki_backup.json')); c=collections.Counter(x['model'].split('.')[0] for x in d); print('total objects:', len(d)); print(dict(sorted(c.items())))"
total objects: 26
{'wiki': 26}
loaddata 恢复(对同一文件重放,实测回显):
./venv/bin/python manage.py loaddata wiki_backup.json
Installed 26 object(s) from 1 fixture(s)
loaddata 按主键 upsert,重复执行不产生脏数据;恢复到新库时先 flush 相关应用或保证目标库干净。
dumpdata --help 实测关键参数(逐行照抄要点):
--format FORMAT Specifies the output serialization format for fixtures.
--indent INDENT Specifies the indent level to use when pretty-printing
output.
--database {default} Nominates a specific database to dump fixtures from.
Defaults to the "default" database.
-e EXCLUDE, --exclude EXCLUDE
An app_label or app_label.ModelName to exclude (use
multiple --exclude to exclude multiple apps/models).
--natural-foreign Use natural foreign keys if they are available.
--natural-primary Use natural primary keys if they are available.
-a, --all Use Django's base manager to dump all models stored in
the database, including those that would otherwise be
filtered or modified by a custom manager.
--pks PRIMARY_KEYS Only dump objects with given primary keys. Accepts a
comma-separated list of keys. This option only works
when you specify one model.
-o OUTPUT, --output OUTPUT
Specifies file to which the output is written.
⚠️ 注意:备份
wiki应用时建议同时备份auth(用户表)与附件/图片目录(/srv/wiki/media),否则恢复后文章里的修订作者与上传文件会缺失。
4.4 交互查询:shell / dbshell
shell -c 单行查询文章路径树(实测回显):
./venv/bin/python manage.py shell -c 'from wiki.models import URLPath; print([p.path for p in URLPath.objects.all()])'
32 objects imported automatically (use -v 2 for details).
['', 'getting-started/', 'xss-test/', 'xss-demo/']
URLPath.path 即 URL 中的 slug 路径,空串是根文章。排查「文章 404 / slug 冲突」时先列这张表。
dbshell 直接进入数据库命令行(SQLite 下即 sqlite3 /srv/wiki/db.sqlite3),--help 实测只有 --database {default} 一个专属参数,其余为 Django 通用参数。
4.5 通知系命令:wiki_notifications_create_defaults 与 notifymail
wiki_notifications_create_defaults(notifications 插件提供):遍历全部文章,为所有者与修订编辑者批量补建「文章编辑」订阅。--help 实测:
usage: manage.py wiki_notifications_create_defaults [-h] [--version]
[-v {0,1,2,3}]
[--settings SETTINGS]
[--pythonpath PYTHONPATH]
[--traceback] [--no-color]
[--force-color]
[--skip-checks]
Import and parse messages directly from a CSV file.
(help 文案 "Import and parse messages directly from a CSV file." 是上游源码遗留错误描述,实际功能是补建订阅,无 CSV 参数。)
直接执行在「编辑者从未初始化通知设置」时会崩,实测完整报错(traceback 关键帧逐行照抄):
File "/srv/wiki/venv/lib/python3.12/site-packages/wiki/plugins/notifications/management/commands/wiki_notifications_create_defaults.py", line 26, in subscribe_to_article
settings_map[user], __ = Settings.objects.get_or_create(
File "/srv/wiki/venv/lib/python3.12/site-packages/django/db/models/query.py", line 669, in create
obj.save(force_insert=True, using=self.db)
File "/srv/wiki/venv/lib/python3.12/site-packages/django_nyt/models.py", line 238, in save
raise ValueError("A user must have a default settings object")
ValueError: A user must have a default settings object
根因:命令内 Settings.objects.get_or_create(user=user) 不带 is_default=True,新建的非默认行在「该用户没有任何默认设置行」时被 django_nyt 的 save() 校验拒绝。凡是绕过 wiki 注册页建号(createsuperuser、admin 后台)且编辑过文章的用户都会触发。
修复:先给涉及用户补默认设置行再重跑。脚本 fix_nyt.py:
from django.contrib.auth import get_user_model
from django_nyt.models import Settings
from wiki.models import Article
U = get_user_model()
involved = set()
for a in Article.objects.all():
if a.owner:
involved.add(a.owner)
for r in a.articlerevision_set.exclude(user=None).values("user"):
involved.add(U.objects.get(id=r["user"]))
print("involved users:", sorted(u.username for u in involved))
missing = [u for u in involved if not Settings.objects.filter(user=u).exists()]
print("users WITHOUT any Settings row:", [u.username for u in missing])
for u in missing:
Settings.objects.create(user=u, is_default=True)
print("after fix:", list(Settings.objects.values("user__username", "is_default")))
实测执行与重跑(逐行照抄):
./venv/bin/python manage.py shell < fix_nyt.py
./venv/bin/python manage.py wiki_notifications_create_defaults
32 objects imported automatically (use -v 2 for details).
involved users: ['admin', 'editor1']
users WITHOUT any Settings row: ['editor1']
after fix: [{'user__username': 'admin', 'is_default': True}, {'user__username': 'editor2', 'is_default': True}, {'user__username': 'editor1', 'is_default': True}]
Created 8 subscriptions on 4 articles
notifymail(django_nyt 提供):把未发送的订阅通知按各订阅频率投递为邮件。它是独立投递进程,Web 请求不会发信,需常驻(--daemon)或定时(--cron)执行。--help 实测专属参数(逐行照抄):
usage: manage.py notifymail [-h] [--daemon] [--cron] [--pid-file PID]
[--domain DOMAIN] [--http-only] [--log-file LOG]
[--no-sys-exit]
[--daemon-sleep-interval SLEEP_TIME] [--now NOW]
[--retries RETRIES]
[--retries-cooldown RETRIES_COOLDOWN] [--version]
[-v {0,1,2,3}] [--settings SETTINGS]
[--pythonpath PYTHONPATH] [--traceback]
[--no-color] [--force-color] [--skip-checks]
Sends notification emails to subscribed users taking into account the
subscription interval
--daemon, -d Go to daemon mode and exit
--cron, -c Do not loop, just send out emails once and exit
--pid-file PID Where to write PID before exiting
--domain DOMAIN Base domain to use for URLs (excluding HTTP protocol).
--http-only Use http:// in URLs instead of https://.
--log-file LOG Where daemon should write its log
--no-sys-exit Skip sys-exit after forking daemon (mainly for testing purposes)
--daemon-sleep-interval SLEEP_TIME
Minimum sleep between each polling of the database.
--now NOW Simulate when to start sending from (mainly for testing purposes)
--retries RETRIES How many time to retry if encountering errors when sending the emails
--retries-cooldown RETRIES_COOLDOWN
Time in seconds to wait before trying again to send the emails
直接前台运行(不带 --cron,进入 send-loop 循环)实测回显——未配置 EMAIL_HOST 时 Django 默认连 localhost:25,被拒:
2026-11-01 12:18:15: INFO - Starting django_nyt e-mail dispatcher
Entering send-loop, CTRL+C to exit
2026-11-01 12:18:15: INFO - Starting send loop at 2026-11-01 12:18:15.975447+00:00
(中间为 smtplib 连接栈的 traceback 帧,略)
ConnectionRefusedError: [Errno 111] Connection refused
--cron 单次投递模式同样因 SMTP 不可达失败(末尾回显一致:ConnectionRefusedError: [Errno 111] Connection refused)。把邮件后端临时切为内存队列(EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend')后 --cron 实测正常启动并完成一轮投递:
2026-11-01 12:19:01: INFO - Starting django_nyt e-mail dispatcher
生产用法二选一:
# 方式一:cron 定时(每分钟)
* * * * * cd /srv/wiki && ./venv/bin/python manage.py notifymail --cron >> /var/log/notifymail.log 2>&1
# 方式二:守护模式(自行写 systemd 单元常驻)
./venv/bin/python manage.py notifymail --daemon --pid-file /run/notifymail.pid --log-file /var/log/notifymail.log
4.6 缩略图清理:thumbnail(sorl-thumbnail)
图片插件上传后按 WIKI_IMAGES_THUMBNAIL_SIZES 各档位生成缩略图并缓存在 key-value 表中,thumbnail 命令负责清理。--help 实测(逐行照抄):
usage: manage.py thumbnail [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS] [--pythonpath PYTHONPATH]
[--traceback] [--no-color] [--force-color]
[--skip-checks]
{cleanup,clear,clear_delete_referenced,clear_delete_all}
Handles thumbnails and key-value store
positional arguments:
{cleanup,clear,clear_delete_referenced,clear_delete_all}
Documentation: https://sorl-thumbnail.readthedocs.io/en/latest/management.html
四个子动作:cleanup(清孤儿缓存项)、clear(清 key-value 记录)、clear_delete_referenced(连同被引用文件一起删)、clear_delete_all(全删)。定期维护用 cleanup 即可(实测回显):
./venv/bin/python manage.py thumbnail cleanup
Cleanup thumbnails ... [Done]
4.7 会话与静态文件:clearsessions / collectstatic
./venv/bin/python manage.py clearsessions
实测退出码 0(无输出即正常),清掉 django_session 表中的过期行;建议 cron 每日一次。
./venv/bin/python manage.py collectstatic --noinput
实测回显:
0 static files copied to '/srv/wiki/static', 380 unmodified.
升级 django-wiki 或改 STATICFILES_DIRS 后重跑,把新静态资源同步到 STATIC_ROOT 供反代直出。
4.8 配置核对:diffsettings 与 check --deploy
./venv/bin/python manage.py diffsettings | grep WIKI_
实测回显(### 标记项目显式覆写的项):
WIKI_ACCOUNT_HANDLING = True ###
WIKI_ACCOUNT_SIGNUP_ALLOWED = True ###
生产上线前安全检查:
./venv/bin/python manage.py check --deploy
实测回显(当前测试环境 DEBUG=True、未配 HTTPS,6 条警告):
WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served only over SSL, you may want to consider setting a value and enabling HTTP Strict Transport Security. Be sure to read the documentation first; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over both SSL and non-SSL connections, you may want to either set this setting True or configure a load balancer or reverse-proxy server to redirect all connections to HTTPS.
?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' indicating that it was generated automatically by Django. Please generate a long and random value, otherwise many of Django's security-critical features will be vulnerable to attack.
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. Using a secure-only session cookie makes it more difficult for network traffic sniffers to hijack user sessions.
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. Using a secure-only CSRF cookie makes it more difficult for network traffic sniffers to steal the CSRF token.
?: (security.W018) You should not have DEBUG set to True in deployment.
System check identified 6 issues (0 silenced).
逐项对应处理见《django-wiki 0.13.0 配置参数详解》「生产配置模板」一节。
4.9 服务托管:gunicorn
生产启动命令(工程目录 /srv/wiki):
cd /srv/wiki
./venv/bin/gunicorn wikisite.wsgi:application -b 0.0.0.0:8000 -w 2 \
--access-logfile /var/log/wiki_access.log --error-logfile /var/log/wiki_error.log \
--pid /run/wiki.pid --daemon
实测 /var/log/wiki_error.log 启动段(逐行照抄):
[2026-11-01 12:46:47 +0000] [1528] [INFO] Starting gunicorn 26.2.0
[2026-11-01 12:46:47 +0000] [1528] [INFO] Listening at: http://0.0.0.0:8000 (1528)
[2026-11-01 12:46:47 +0000] [1528] [INFO] Using worker: sync
[2026-11-01 12:46:47 +0000] [1529] [INFO] Booting worker with pid: 1529
[2026-11-01 12:46:47 +0000] [1530] [INFO] Booting worker with pid: 1530
[2026-11-01 12:46:47 +0000] [1528] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
改配置后的平滑重启(实测:向主进程发 SIGHUP,旧 worker 退出、新 worker 接管,服务不中断):
kill -HUP $(cat /run/wiki.pid)
tail -6 /var/log/wiki_error.log
实测日志回显(主进程 pid 2009,worker 2010/2011 换为 2141/2143):
[2026-11-01 13:24:15 +0000] [2141] [INFO] Booting worker with pid: 2141
[2026-11-01 13:24:15 +0000] [2009] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
[2026-11-01 13:24:15 +0000] [2143] [INFO] Booting worker with pid: 2143
[2026-11-01 13:24:15 +0000] [2009] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
[2026-11-01 13:24:15 +0000] [2011] [INFO] Worker exiting (pid: 2011)
[2026-11-01 13:24:15 +0000] [2010] [INFO] Worker exiting (pid: 2010)
存活验证:
curl -s -o /dev/null -w 'GET /: %{http_code}\n' http://127.0.0.1:8000/
curl -s http://127.0.0.1:8000/ | grep -o '<title>[^<]*</title>' | head -1
GET /: 200
<title>Home - django-\/\/ i K |</title>
(<title> 里的怪串是 django-wiki 默认首页标题中内嵌 logo 字符画的一部分,属正常现象。)
五、注意事项
notifymail必须独立调度:邮件不在 Web 进程内发送。忘了跑它,用户订阅了也收不到任何邮件——这是「通知不生效」的第一排查点。- 备份三件套:
dumpdata wiki只覆盖文章数据;完整备份 = fixture +auth/auth_permission导出 +/srv/wiki/media目录(附件与图片)+db.sqlite3冷备。 makemigrations不要随手跑:见「六、常见问题」6.2,0.13.0 在 Django 6.x 下存在迁移噪音。- 所有写命令(
migrate/loaddata/flush)执行前先dumpdata:flush会清空数据库,不可逆。 - 命令通用参数:每个子命令都支持
-v {0,1,2,3}、--settings SETTINGS、--pythonpath PYTHONPATH、--skip-checks(实测--help均含),多环境共用工程时用--settings指定不同 settings 模块最干净。
六、常见问题
6.1 changepassword 脚本化失败:EOFError / termios.error
现象:echo q1w2e3r4 | manage.py changepassword root 报:
Warning: Password input may be echoed.
This password is too common.
termios.error: (25, 'Inappropriate ioctl for device')
EOFError
定位:两层叠加——① changepassword 用 getpass 要求 TTY,管道输入触发回退读取并最终 EOFError;② 即便 TTY 输入,q1w2e3r4 也会被 CommonPasswordValidator 拒绝(This password is too common.)。
解决:改强密码走交互 TTY;批量改密改用 Django API(set_password 不经过校验器):
./venv/bin/python manage.py shell -c '
from django.contrib.auth import get_user_model
u = get_user_model().objects.get(username="root")
u.set_password("Q1w2e3r4!xZ")
u.save()
print("password updated for", u.username)
'
实测回显:
32 objects imported automatically (use -v 2 for details).
password updated for root
6.2 makemigrations --check 总是 exit=1、提示生成 alter 迁移
现象(实测回显):
Migrations for 'wiki':
venv/lib/python3.12/site-packages/wiki/migrations/0004_alter_article_id_alter_articleforobject_id_and_more.py
~ Alter field id on article
~ Alter field id on articleforobject
~ Alter field id on articleplugin
~ Alter field id on articlerevision
~ Alter field id on revisionpluginrevision
~ Alter field id on urlpath
Migrations for 'wiki_attachments':
venv/lib/python3.12/site-packages/wiki/plugins/attachments/migrations/0003_alter_attachmentrevision_id.py
~ Alter field id on attachmentrevision
exit=1
定位:django-wiki 0.13.0 发布时模型主键与 Django 6.x 项目默认 DEFAULT_AUTO_FIELD = BigAutoField 存在差异,makemigrations 检测到「可把 id 改为 BigAuto」的待生成迁移。这是上游包内迁移状态问题,不是你的库坏了——showmigrations 里 wiki 各应用全部 [X]、check 无 issues 即无需处理。
解决:不要在 CI 里用 makemigrations --check 卡 django-wiki 工程的门禁;确要消除噪音,可把上述 alter 迁移生成在工程内应用并执行(会改表类型,SQLite 下 Django 会建新表迁移数据,务必先备份)。
6.3 notifymail 报 Connection refused
见 4.5 节实测:默认 EMAIL_HOST=localhost:25 不可达。配置真实 EMAIL_HOST/EMAIL_PORT 后重跑;无 SMTP 服务器联调时临时用 locmem 后端验证投递逻辑。
6.4 执行 wiki_notifications_create_defaults 报 ValueError: A user must have a default settings object
完整根因分析与修复脚本见 4.5 节(实测修复后输出 Created 8 subscriptions on 4 articles)。要点:命令不会为「从未初始化通知设置」的用户自动建默认 Settings,先跑 fix_nyt.py 补齐即可。
6.5 升级 django-wiki 版本后的命令顺序
固定三步(每步实测均有回显可核对):
./venv/bin/pip index versions wiki # 先查当前可用版本(实测最新稳定版为 0.13.0)
./venv/bin/pip install -U wiki # 不带版本号即升级到 PyPI 最新稳定版
./venv/bin/python manage.py migrate # 新迁移落库
./venv/bin/python manage.py collectstatic --noinput
./venv/bin/python manage.py check # 确认 0 issues
kill -HUP $(cat /run/wiki.pid) # 平滑重启 gunicorn
七、参考链接
- Django management commands 官方文档:https://docs.djangoproject.com/en/6.0/ref/django-admin/
- django-wiki 官方文档(Commands 与 Installation):https://django-wiki.readthedocs.io/en/master/
- django-wiki GitHub 仓库:https://github.com/django-wiki/django-wiki
- django-nyt(notifymail 来源):https://django-nyt.readthedocs.io/
- sorl-thumbnail 管理命令:https://sorl-thumbnail.readthedocs.io/en/latest/management.html
- gunicorn 部署 Django:https://docs.gunicorn.org/
- 站内相关:《django-wiki 介绍与选型指南》《Debian 13 安装 django-wiki 0.13.0 指南》《django-wiki 0.13.0 配置参数详解》