Django的startproject和startapp不能混用,因为前者创建完整项目容器(含settings.py、manage.py等),后者仅生成可插拔App;跳过startproject会导致manage.py缺失,后续命令报ModuleNotFoundError。

为什么 Django 的 startproject 和 startapp 不能混用
新建博客系统时,很多人直接在项目根目录下运行 python manage.py startapp blog,却忘了先用 django-admin startproject myblog 创建外层项目容器。前者生成的是可插拔的 App(比如 blog、accounts),后者才是整个 Django 站点的配置中心(含 settings.py、asgi.py)。如果跳过 startproject,manage.py 根本不存在,后续所有命令都会报 ModuleNotFoundError: No module named 'django.core.management'。
实操建议:
立即学习“Python免费学习笔记(深入)”;
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 始终先执行
django-admin startproject myblog,再cd myblog,最后python manage.py startapp blog - 确认
myblog/blog目录下有models.py、views.py,且myblog/myblog/settings.py的INSTALLED_APPS已添加'blog' - 别把 App 放在项目根目录外,Django 不会自动发现路径不规范的 App
如何让 Post 模型支持 Markdown 渲染和摘要自动截取
Django 默认只存纯文本,但博客正文需要保留格式,又不能每次手动写 HTML。直接在模板里用 {{ post.body|safe }} 很危险——用户输入的恶意脚本会被执行。更稳妥的做法是在模型层完成转换,并缓存渲染结果。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 安装
markdown和bleach:pip install markdown bleach - 在
blog/models.py中为Post添加body_html字段(TextField),并在save()方法里调用markdown.markdown()转换,再用bleach.clean()过滤危险标签 - 摘要不要靠前端
{{ post.body|truncatewords:50 }}——它会截断 HTML 标签导致页面错乱;改用 Python 的strip_tags()+textwrap.shorten()在模型中预生成excerpt字段
为什么 urls.py 套两层 path() 就 404
新手常把全局 myblog/urls.py 和 App 内 blog/urls.py 的路由写成嵌套形式,比如在主 urls.py 里写 path('blog/', include('blog.urls')),又在 blog/urls.py 里写 path('post/<pk>/', views.post_detail)</pk>,结果访问 /blog/post/1/ 却 404。问题出在子路由没声明前缀:Django 的 include() 会把匹配到的 URL 前缀剥离后才传给子路由,所以子 urls.py 的 path() 应该从 '' 或 '/' 开始,而不是重复写 'blog/'。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 主
urls.py:保留path('blog/', include('blog.urls')) - 子
blog/urls.py:写path('', views.post_list, name='post_list')和path('<pk>/', views.post_detail, name='post_detail')</pk>,这样完整路径才是/blog/和/blog/1/ - 调试时加一句
print(request.path)在视图开头,确认实际收到的路径是否符合预期
runserver 能跑通,但部署到 Nginx + Gunicorn 就白屏或静态文件 404
本地开发用 python manage.py runserver 时,Django 自动处理静态文件(CSS/JS/图片);但生产环境必须由 Web 服务器(如 Nginx)直接提供,否则 Gunicorn 只负责动态请求,静态资源全 404。更隐蔽的问题是,Django 的 DEBUG=False 下,runserver 会直接拒绝服务静态文件,连本地都看不到样式。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 开发阶段确保
DEBUG=True,并运行python manage.py collectstatic --noinput把所有 App 的静态文件合并到STATIC_ROOT指定目录 - Nginx 配置里必须显式声明
location /static/指向STATIC_ROOT路径,例如alias /var/www/myblog/static/;(注意末尾斜杠) - 别信“只要开了 DEBUG 就能省事”——上线前务必切到
DEBUG=False并测试静态资源是否可访问,这是最常被跳过的验证步骤

















