
写这篇东西的念头源于我自己第一次搭 Django 项目时差点把电脑拆了的经历。那时候刚把 Python 装好照着网上的教程敲pip install django结果要么安装超时要么敲django-admin提示“不是内部或外部命令”折腾一晚上连第一个startproject都没跑出来。后来在课程设计里帮学弟学妹看代码才发现这些所谓的“创建 Django 项目遇到的问题”其实高度雷同版本不对、环境混乱、路径没配好、迁移顺序弄反翻来覆去就是那么几类。所以这篇文章不是那种面面俱到的 Django 教程而是聚焦在“创建项目”这个从零到一的阶段把你在安装 Django、新建项目、注册应用、连接数据库、启动开发服务器这一路上最容易踩的坑全部摊开讲清楚。不管你是刚接触 Django 的学生、从其他语言转过来的后端开发还是准备用 Django 做毕业设计但被环境卡住的新手这篇内容基本能覆盖你前两周遇到的大部分报错。我会按照实际创建项目的顺序来写每段都附上我当时是怎么处理的以及为什么这么做。1. 环境准备阶段版本对齐和虚拟环境是第一个分水岭创建 Django 项目的第一步不是敲命令而是把 Python 和 Django 的版本关系搞清楚。很多人上来就直接pip install django装完了才发现项目根本跑不起来然后在社区里发帖问“为什么我按教程做的却报错”底下评论第一条永远是“你版本不对”。这话听着刺耳但确实是绝大多数问题的根源。1.1 Python 与 Django 的版本兼容问题Django 对 Python 版本有明确要求不是说你装了 Python 3.12 就一定能跑 Django 3.2。我把常用的对应关系整理了一下你创建项目前先对一下自己的版本Django 版本支持的 Python 版本说明Django 5.03.10 - 3.12当前最新主版本特性多但对老项目兼容性要求高Django 4.2 LTS3.8 - 3.12长期支持版本推荐新手和生产环境使用Django 3.2 LTS3.6 - 3.10较老但稳定部分老教程还在用Django 2.2 LTS3.5 - 3.9基本不推荐新项目使用我自己吃过一次亏是帮别人看一个报错终端里显示django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured。查了半天才发现他用 Python 3.11 跑 Django 3.0这个组合本身就存在兼容问题。更常见的报错是ImportError: cannot import name force_text from django.utils.encodingDjango 4.0 删掉了旧名字老代码直接崩。所以我的建议是新项目无脑选 Django 4.2 LTS配套 Python 3.10 或 3.11。别追新追新意味着教程、第三方库、网上问答可能都还没跟上。装完以后跑一句python -m django --version能正常显示版本号说明基础环境已经通了。1.2 虚拟环境为什么新手必须用我见过太多人图省事把项目依赖直接装进全局 Python。一开始没问题等第二个项目需要不同版本的 Django 时就开始互相打架了这个项目要 4.2那个项目要 3.2全局环境只有一个你卸载哪个都会破坏另一个项目。虚拟环境存在的意义就是隔离。Python 自带的venv完全够用不需要额外装 virtualenvwrapper 之类的工具# 创建虚拟环境venv 是目录名可以用 .venv python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate激活之后你的终端提示符前面会多出(venv)字样这时候再pip install django安装位置就落在虚拟环境里跟全局环境彻底隔离。但这里有一个 Windows 特有的坑激活时报错无法加载文件 activate.ps1因为在此系统上禁止运行脚本。这是 PowerShell 默认执行策略限制导致的解决办法是用管理员权限打开 PowerShell执行Set-ExecutionPolicy RemoteSigned然后按 Y 确认。如果不想动执行策略也可以直接用cmd窗口运行venv\Scripts\activate.bat一样能激活。还有一次我在 PyCharm 的 Terminal 里死活激活不了后来发现 PyCharm 默认用的是 PowerShell而项目解释器已经指向了 venv根本不需要手动激活——直接在右下角切换解释器就行。1.3 pip 安装 Django 失败的解决办法pip 安装 Django 最常见的现象就是卡在Downloading然后超时或者报ReadTimeoutError。原因不用多说默认的 PyPI 源在国外网络一不稳就废。解决方法很简单用国内镜像源pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple清华大学、阿里云、中科大的 PyPI 镜像都行挑一个你网络访问最快的。嫌每次打参数太麻烦可以永久写入配置pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple配置改完以后再pip install django速度就舒服多了。另外提醒一句安装完以后别急着创建项目先检查一下pip list里 Django 的版本是不是你想要的。如果发现装成了未来版本用pip uninstall django卸载再重新指定版本号安装pip install django4.2.16版本号在 Django 官方 release 页面都能查到选最新的小版本就行修了很多 bug。2. 项目创建命令和目录结构的那些坑环境弄好之后终于到了正式创建项目这一步。django-admin startproject和python manage.py startapp这两条命令看着简单实际用起来坑也不少尤其是新手容易卡在“命令找不到”和“项目名不能叫什么”这种小事上。2.1 django-admin startproject命令找不到与项目命名在 Windows 上很多人的第一反应是直接敲django-admin startproject mysite然后提示django-admin 不是内部或外部命令。原因很简单Django 安装后django-admin.exe放在 Python 的Scripts目录下这个目录没有加到系统 PATH 里。你不一定要去改环境变量更稳妥的方式是用模块调用python -m django startproject mysite用python -m django的好处是它会自动使用你当前 Python 环境对应的 Django避免多个版本并存时调用错命令。这个习惯我一直保留到现在后面很多管理命令也推荐用python manage.py xxx的格式就是同一个道理。项目名字的坑也得注意。Django 内部有一些保留字你用它们当项目名后续会出各种莫名其妙的错误。比如项目名不能叫test因为和 Python 标准库test冲突你后面跑测试会报ModuleNotFoundError。也不能叫django这个不用解释。还有project、site这类名字容易造成路径解析混乱。我建议项目名用简短、小写、不带下划线的英文单词比如mysite、blogproject、shop。创建成功后会生成这样的结构mysite/ ├── manage.py └── mysite/ ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py有同学问为什么外层mysite和内层mysite同名看得很晕。外层目录是项目的容器放 manage.py 和各个 app内层目录是项目的配置包settings.py、urls.py、wsgi.py 都在这。你可以把外层目录理解成“整个工程的根目录”内层是“全局配置中心”。2.2 startapp 创建应用注册才是关键项目建好后下一步就是创建 app。这里有个概念要分清Django 里的“项目”和“应用”是两回事。项目是配置和入口应用才是真正写业务逻辑的地方。博客应用、用户应用、订单应用都是一个个独立的 app挂在项目下面。创建应用的命令是python manage.py startapp blog执行后会生成 blog 目录里面有models.py、views.py、admin.py等文件。很多新手到这里就以为自己创建完 app 了直接去写 models然后发现python manage.py makemigrations返回No changes detected一脸懵。原因是你创建了 app但还没有把它“告诉”Django。需要在settings.py的INSTALLED_APPS列表里加上INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, blog, # 这里 ]INSTALLED_APPS这个配置项作用就是告诉 Django“我这个项目启用了哪些应用”。没注册的应用Django 不会执行它的 models、不会创建数据表甚至模板也不一定找得到。这个坑我见过太多人踩了所以特意啰嗦一遍创建 app 以后第一件事就是去注册然后再写代码。另外app 名字也尽量别跟 Python 标准库重名。我叫过一次test结果后面写单元测试时所有import test都串了排查了半天。还有site、utils这种常见的模块名起名时最好先确认一下。2.3 PyCharm 导入已有 Django 项目的问题这个场景是热搜词里出现过的也是我在帮学弟学妹调代码时最常遇到的情况之一。你从学长那里拷了一个 Django 项目或者从 Git 仓库 clone 下来用 PyCharm 打开以后满屏报红python manage.py runserver一运行就是No module named django。先说根本不是代码的问题是你 PyCharm 的解释器选错了。PyCharm 默认可能用的是系统 Python而 Django 装在项目的虚拟环境里。解决路径是左下角或右下角的解释器位置点进去选择Add Interpreter选Existing environment然后把路径指向你之前创建好的venv目录下的Scripts/python.exe。选对解释器以后还有一个常见报错是运行项目时提示ModuleNotFoundError: No module named mysite.settings。这通常是因为 Run Configuration 没有配置环境变量DJANGO_SETTINGS_MODULE。打开Edit Configurations在Environment variables里加上DJANGO_SETTINGS_MODULEmysite.settings然后Working directory一定要指向 manage.py 所在的目录也就是外层项目根目录。我之前见过有人在 PyCharm 里运行manage.py工作目录却被默认设置成了venv目录结果报了一堆路径错误折腾好久才发现是这个问题。项目导入成功以后第一件事不是急着改代码而是先打开终端PyCharm 自带 Terminal确认虚拟环境激活状态然后跑一遍python manage.py check。这个命令会快速检查项目配置、模型、URL 等有没有明显问题比直接 runserver 报错信息更友好。3. 数据库与迁移你遇到的 90% 的数据库错误在这创建项目时 Django 默认使用的是 SQLite这是一个不需要额外安装数据库服务的文件型数据库学起来特别省心。但就是在这个“最省心”的阶段也有几个特别容易翻车的点尤其是第一次跑python manage.py migrate就报错的人不在少数。3.1 migrate 首次执行失败的原因新项目第一次迁移是把 Django 内置应用比如 admin、auth、session的数据表创建到数据库里。很多人执行migrate时遇到django.db.utils.OperationalError: unable to open database file这个报错对新手来说特别迷惑明明我什么都没配置怎么就打不开数据库了原因通常是 SQLite 数据库文件默认叫db.sqlite3要生成的目录不存在或者当前用户没有写权限。比如你把项目放在某些需要管理员权限才能写入的目录下Python 进程创建不了文件就报这个错。解决办法有两种一是确保你的项目根目录当前用户可以写入右键文件夹看属性把写权限打开或者把项目挪到自己的用户目录下二是手动改数据库路径在settings.py里配置DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } }BASE_DIR是项目根目录的绝对路径/连接符在 Python 3.9 中会自动处理跨平台路径分隔符所以在 Windows 和 macOS 上都没问题。还有一类典型问题是你本来用 SQLite 跑得好好的后来想换成 MySQL 或者 PostgreSQL改完DATABASES配置以后直接 runserver报错ModuleNotFoundError: No module named MySQLdb。这是因为 Django 操作数据库需要对应的驱动包MySQL 要装mysqlclient或pymysqlPostgreSQL 要装psycopg2-binarypip install mysqlclient # 或者 pip install pymysql pip install psycopg2-binary如果你用了pymysql还要在项目的__init__.py里做一次 monkey patchimport pymysql pymysql.install_as_MySQLdb()这个操作的意思是让 Django 把MySQLdb映射到pymysql上部分教程会要求加这一步。不过能用mysqlclient就直接用它是 MySQL 官方推荐的驱动性能相对更好。3.2 模型字段与迁移顺序数据库迁移还有一个非常经典的顺序问题先makemigrations再生migrate这个顺序千万别搞反。有同学写好了models.py直接migrate然后发现数据库里根本没建表回到终端一看Django 提示 “No changes detected”。这不是因为你表没建而是因为你跳过了“生成迁移文件”这一步。makemigrations的作用是根据你的模型变化生成迁移脚本就是一个 Python 文件记录你改了哪些字段migrate才是真正把这些脚本执行到数据库里。两者是“先生成、再执行”的关系。正确流程是python manage.py makemigrations python manage.py migrate如果执行完makemigrations以后系统提示No changes detected那九成是 app 根本没注册回到 2.2 去检查INSTALLED_APPS。另一个人人都可能遇到的报错是你在模型里加了一个字段忘了跑迁移然后去页面上操作数据库返回OperationalError: no such column: blog_post.title。这类报错在开发期特别常见因为 Django 开发服务器不会自动帮你同步数据库。每次改了models.py都要养成习惯跑一遍这两条命令哪怕只是加了一个字段。模型字段写的时候也要小心on_delete参数。Django 2.0 以后ForeignKey 必须要指定on_delete否则会报TypeError: __init__() missing 1 required positional argument: on_delete。新手最常写的class Comment(models.Model): post models.ForeignKey(Post, on_deletemodels.CASCADE)CASCADE表示关联的文章删了评论也一起删。如果希望删了文章保留评论可以用SET_NULL并配合nullTrue。这块策略要根据业务逻辑来定别图省事全用 CASCADE。3.3 时区与时间的坑时区问题是数据库层面另一个几乎人人都会中招的细节。Django 默认配置里TIME_ZONE UTCUSE_TZ True。这意味着你往数据库里存的时间是 UTC 标准时间而我们的本地时间比 UTC 快 8 个小时。你在页面上显示时间会发现自己发布的文章莫名其妙少了 8 小时。我踩这个坑是在一个博客项目里文章发布时间永远比实际时间早 8 个小时当时一度怀疑是服务器时钟出了问题。后来查了文档才知道是时区没配。解决办法TIME_ZONE Asia/Shanghai USE_TZ TrueUSE_TZ True建议保持因为它是 Django 官方推荐的实践好处是时间在世界各地显示时能自动转换到本地时区。你只需要把TIME_ZONE设成自己的时区即可。需要注意的是如果你在代码里直接用了datetime.datetime.now()这个函数返回的是本地时间而不是 UTC 时间在USE_TZ True的情况下存储到 DateTimeField 字段时可能触发警告甚至报错。正确做法是用 Django 提供的timezone.now()from django.utils import timezone now timezone.now()timezone.now()会尊重你的时区设置统一返回 UTC 时间存储显示都按照TIME_ZONE设置来转换省心很多。4. 启动运行与静态文件dev 服务器也不省心环境、项目、数据库都搞定了终于到了激动人心的python manage.py runserver。但别高兴太早开发服务器启动阶段还有一批坑在等着你。这一节我按实际使用频率把最可能碰到的几个问题都摆出来。4.1 runserver 端口冲突和管理后台 404启动开发服务器最常见的报错Error: That port is already in use.字面意思就是这个端口已经被别的进程占了。有时候是你自己之前的 runserver 没关干净有时候是其他程序在占用 8000 端口。解决办法是先找出占用端口的进程Windows 下netstat -ano | findstr 8000看到端口对应 PID 后到任务管理器里找到这个进程结束它。macOS / Linux 下可以用lsof -i:8000查看。嫌麻烦的话更干脆的方式是换一个端口python manage.py runserver 8080顺带说一句Django 开发服务器默认监听的是127.0.0.1也就是只能本机访问。如果你想让局域网里的手机或另一台电脑访问你的项目需要指定 IPpython manage.py runserver 0.0.0.0:8000这样监听所有网络接口同一局域网内的设备可以尝试用你电脑的 IP 加端口打开页面。不过这样有个连带问题就是会触发 4.2 要说的ALLOWED_HOSTS报错。还有一个配置性的坑新手访问/admin管理后台发现返回 404。原因是它根本没被注册到 URL 路由里。默认生成的urls.py里其实已经包含了 adminfrom django.contrib import admin from django.urls import path urlpatterns [ path(admin/, admin.site.urls), ]如果你看到文件里没有这一行或者你之前是手动创建的项目忘了加把上述代码补上就行。4.2 DisallowedHostALLOWED_HOSTS 配置第一次用runserver 0.0.0.0:8000之后用手机访问电脑的 IP结果浏览器显示 400 Bad Request页面标题是 DisallowedHost。这是 Django 的安全机制在起作用默认情况下ALLOWED_HOSTS是空的只允许localhost和127.0.0.1访问其他 Host 全部拒绝。解决办法是在settings.py里修改ALLOWED_HOSTS [*]生产环境千万别这么写等于允许任何域名访问你的站点容易遭受恶意请求。开发阶段这样写没问题省得每天改 IP。等上线了再限制成正式域名ALLOWED_HOSTS [www.example.com, example.com]如果你服务器有固定的公网 IP也可以直接把 IP 加进去。4.3 模板和静态文件加载不出来模板加载问题几乎每个新手都会经历。最常见的报错是TemplateDoesNotExist: blog/index.html。排查思路分三步第一步检查settings.py里的TEMPLATES配置。默认生成的配置里APP_DIRS为 True意思是 Django 会去每个已注册 app 的templates目录里找模板。如果这个值是 FalseDjango 就不会自动搜索 app 里的模板目录。第二步检查模板文件的位置。Django 约定模板应该放在blog/templates/blog/index.html。注意这个“重复的 blog 目录”是故意的目的是避免多个 app 里同名模板互相覆盖。如果你直接放在blog/templates/index.html配合APP_DIRS True也能找到但一旦有其他 app 也有index.html就有冲突风险。第三步确认 app 是否在INSTALLED_APPS里。这一步在 2.2 已经强调过不重复了。静态文件加载不出来的问题也很常见。表现是页面能打开但 CSS 全部失效图片全部 404。开发阶段静态文件的处理逻辑是这样Django 通过django.contrib.staticfiles这个内置 app 来自动收集并服务静态文件。只要你在模板里正确使用{% load static %} link relstylesheet href{% static css/style.css %}然后settings.py里配好STATIC_URL /static/开发服务器就能直接找到每个 app 下的static目录里的文件。如果你把静态文件放在项目根目录下的static文件夹里需要在 settings.py 里额外添加STATICFILES_DIRS [ BASE_DIR / static, ]否则 Django 不会主动去这个目录找。还有一个常见误区有同学为了看生产效果在settings.py里把DEBUG改成False然后刷新页面发现所有静态文件都消失了。这是因为DEBUG False时 Django 不再自动提供静态文件服务必须执行python manage.py collectstatic把散落在各处的静态文件收集到一个统一目录再配置 Web 服务器来提供这些文件。开发阶段别改DEBUG等你研究明白生产部署再说。5. 错误排查思路与速查表前面列的都是具体问题这一节我聊聊方法论重点是从“见一个报错搜一个报错”的状态里走出来逐步建立自己的排查框架。毕竟创建 Django 项目阶段的问题翻来覆去就是那些掌握正确的排查思路后面写业务代码时会顺畅很多。5.1 如何正确看 Django 报错信息新手遇到报错的第一反应是慌第二反应是复制最后一行去搜索引擎或 AI 问答里搜。但我建议你把终端里完整的 Traceback 从头到尾看一遍尤其是这几部分异常类型ModuleNotFoundError、OperationalError、ImproperlyConfigured这些已经告诉你大概方向。最后一段“报错堆栈”中你项目里的文件路径真正的错误往往出现在你自己写的文件里而不是 Django 框架内部。异常信息最后那句话里提到的变量名、字段名、文件名通常直接对应到你代码里某个位置。举个例子报错信息里写No module named blog那你首先要查的是 blog 目录是否存在、是否在INSTALLED_APPS里注册过、PyCharm 解释器路径是否正确而不是复制整段到网上找答案。Django 自带的 debug 页面也很有用。只要DEBUG True页面报错时会显示详细的异常位置、周边代码、请求信息、SQL 等等还会把容易导致问题的原因高亮。我见过有人打开 debug 页面只看第一行完全忽略下面的请求信息面板。其实里面有一个专门显示settings配置的展开项能帮你快速确认INSTALLED_APPS、DATABASES等关键配置有没有生效。另外如果你用的是 PyCharm可以在manage.py上右键选择Debug而不是Run。这样运行时遇到异常会自动停在出错的那一行你可以直接查看局部变量的值比自己瞎猜要高效很多。为了把排查过程记录下来我后面基本都会在settings.py里配一段日志import os LOGGING { version: 1, disable_existing_loggers: False, handlers: { file: { level: DEBUG, class: logging.FileHandler, filename: debug.log, }, }, loggers: { django: { handlers: [file], level: DEBUG, propagate: True, }, }, }配置好以后只要 Django 打印日志都会同步写入根目录下的debug.log。页面报错时如果终端信息被刷掉了去这个文件里看完整日志比翻终端历史方便得多。5.2 常见报错速查表我整理了一张创建 Django 项目阶段最高频的报错速查表你可以直接收藏遇到问题先对号入座报错信息常见原因解决方法ModuleNotFoundError: No module named django解释器不对或 Django 未安装到当前环境确认虚拟环境已激活pip list检查django.core.exceptions.ImproperlyConfigured版本不匹配或环境变量配置缺失检查 Python 与 Django 版本兼容性检查DJANGO_SETTINGS_MODULEImportError: cannot import name xxx代码用了旧版本 API 或拼写错误对比当前 Django 版本的 API 文档OperationalError: unable to open database file数据库路径目录不可写检查项目目录写权限或修改DATABASES中的路径OperationalError: no such table: xxx模型迁移遗漏执行makemigrations和migratedjango.db.utils.ProgrammingError数据库表结构与模型不同步重新生成迁移并迁移必要时清掉数据库重来TemplateDoesNotExist模板路径不对或 app 未注册检查TEMPLATES配置、模板目录位置、INSTALLED_APPSDisallowedHostALLOWED_HOSTS未包含请求域名开发环境设为[*]FieldError: Cannot resolve keyword查询字段名写错或关联关系没配对检查模型的字段名和外键关联TypeError: __init__() missing 1 required positional argument: on_deleteForeignKey 缺少on_delete参数补充on_deletemodels.CASCADE等取值django.urls.exceptions.NoReverseMatchURL 反向解析没有匹配到路由检查urls.py中name参数和应用内路由app_name这里特别说一下NoReverseMatch这个报错在项目里写 URL 跳转时特别常见。通常是因为你在模板里写了{% url blog:detail post.id %}但 urls.py 里没有给detail这个路由起名叫detail或者没有在应用 urls.py 里设置app_name blog。排查时打开 urls.py确认path的name参数和应用内的app_name。5.3 推荐开发期工具建好项目以后强烈建议装一个django-debug-toolbar这个东西对开发期排查问题帮助很大。安装和配置很简单pip install django-debug-toolbar然后在settings.py的INSTALLED_APPS里加上debug_toolbar在urls.py里注册from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(__debug__/, include(debug_toolbar.urls)), ]运行项目后页面右侧会出现一个调试侧边栏能看到当前请求执行的 SQL 语句数、耗时、模板渲染时间、请求头等等。对新手来说最大的价值是能直观看到“我写了一个查询居然执行了 30 条 SQL”从而尽早意识到查询优化的重要性。另一个工具是django-extensions它提供的shell_plus比默认的 manage.py shell 好用太多pip install django-extensions注册到INSTALLED_APPS后运行python manage.py shell_plus它会自动导入项目里的所有模型你想直接查数据、调接口不用手动一个个 import非常顺手。搭配 IPython 一起用体验接近专业 IDE 里的交互式环境。最后再推荐一个我个人的习惯在settings.py底部加一小段只在开发环境生效的配置用来打印所有 SQL 语句LOGGING[loggers][django.db.backends] { handlers: [console], level: DEBUG, }这个配置会把数据库执行的每条 SQL 都打印到终端里。排查 ORM 查询特别有用你能看到 Django 到底帮你翻译成了什么样的 SQL也能发现竟然执行了这么多查询。最后帮很多人看过创建 Django 项目时遇到的问题之后我最大的感受是真正卡住人的往往不是 Django 本身多高深而是环境、版本、注册这些基础动作没做到位。只要你坚持用虚拟环境、先对齐版本再动手、按照“创建 app 就注册、改模型就跑迁移、看报错就看完整堆栈”这几个习惯来操作前期的坑能避开一大半。另外一个小建议新项目建好以后先跑一遍python manage.py check再跑一遍python manage.py migrate最后runserver。三步都顺利通过再开始写业务代码。这个流程花不了两分钟但能帮你把环境问题、配置问题、数据库问题全部提前暴露而不是写了一半才突然冒出来。创建 Django 项目这件事说到底就是“按规矩来别跳步”。把上面的坑都趟平之后你会发现 Django 的后续开发其实非常顺畅。