Django入门教程:搭建你的第一个Python网站(附血泪踩坑记录)

GoRoutine散步
2025-12-13 07:43
阅读 779

上周五晚上十点半,我瘫在电脑前,一边啃着冷掉的外卖,一边盯着屏幕上 ModuleNotFoundError: No module named 'django' 的报错,心里默默问候了 Python 的包管理机制八百遍。那一刻,我真的想把我的 MacBook 直接从阳台扔下去——不是因为 Django 有多难,而是因为明明在国外用 Go 写微服务写得挺顺,回国后却被产品经理一句“咱们先做个 MVP 吧”给拽进了全栈深水区

大家好,我是刚从英国某 Top 10 硕士毕业回国不久的前端/后端/DevOps/产品狗(自我认知已混乱),目前在家远程办公,靠 VSCode + 一堆插件苟活。之前在国外实习主要用 Go 搞后端服务,对 Python 只停留在“能跑脚本”的水平。结果回国面试时被问:“会 Django 吗?”我硬着头皮说“会”,然后……现在每天都在补这个“会”字背后的债。

今天这篇不是那种“Hello World 三行代码搞定”的假大空教程,而是实打实地记录我从零搭建第一个 Django 网站时踩过的坑、绕过的弯、以及差点被线上事故送走的惊魂时刻。如果你也正被老板/PM/自己逼着学 Django,希望这篇能帮你少熬两个通宵。


为啥选 Django?Go 不香吗?

先说背景。我们团队原本是 Go 技术栈,轻量、并发强、部署简单,是我心中的白月光。但这次要做一个内部管理后台,需求极其简单:增删改查 + 用户登录 + Excel 导出。领导拍板:“这种 CRUD 项目用 Django 半天搞定,Go 太重了。”

我当时内心 OS:Django 全家桶?那不就是“自带厨房、冰箱、甚至厨师”的框架吗? 但转念一想,确实——用户系统、Admin 后台、ORM、表单验证……这些轮子 Django 都给你造好了,何必自己拿 Go 从零造?

于是,我含泪卸载了 Goland(开玩笑,没卸,只是切换了 workspace),打开了 VSCode,装上了 Python Extension Pack、Django Snippets、Pylance 一整套插件全家桶,准备开启“真·全栈”之旅。


环境搭建:别信官方文档的“简单三步”

Django 官方文档说:“pip install django 就完事了。”
现实是:你的 Python 版本、虚拟环境、PATH、还有那个神秘的 python3python 到底谁是谁的问题,能让你在第一步就卡死。

我在 Mac 上用的是 pyenv 管理多个 Python 版本,结果 pip install 装到了系统 Python 里,而 VSCode 默认用的是 pyenv 的 3.11。一顿操作猛如虎,运行 django-admin startproject mysite 时直接报错:

-bash: django-admin: command not found

血泪经验:务必在虚拟环境中操作!

# 创建虚拟环境(推荐用 venv,别碰 conda,除非你想和 Jupyter 打一辈子交道)
python3 -m venv django_env

# 激活
source django_env/bin/activate

# 再装 Django
pip install django

# 验证
which django-admin  # 看看是不是在虚拟环境里

另外,VSCode 的 Python 解释器一定要手动切换到虚拟环境里的那个!不然你写代码时 import 能飘红到你怀疑人生。


第一个 App:你以为的“快速上手”,其实是“快速入坑”

执行 python manage.py startapp blog,目录结构出来了,看起来很清晰。但当我试图在 views.py 里写个返回 JSON 的接口时,问题来了:

from django.http import JsonResponse

def post_list(request):
    return JsonResponse({"posts": []})

本地跑没问题,但一旦加上数据库查询,页面就 500。查日志发现:

TypeError: Object of type 'QuerySet' is not JSON serializable

哦对!Django 的 ORM 查询结果不能直接塞进 JSON。国外用惯了 Go 的 json.Marshal 自动处理 struct,回来写 Python 得手动序列化

解决方案?要么用 model_to_dict,要么上 Django REST framework(DRF)。但为了 MVP,我选择了最糙快猛的方式:

from django.core import serializers
import json

def post_list(request):
    posts = Post.objects.all()
    data = serializers.serialize('json', posts)
    return HttpResponse(data, content_type="application/json")

虽然丑,但能跑。上线前记得换成 DRF,否则测试同学会拿着 Postman 把你钉在耻辱柱上


前端整合:Django 模板 vs 现代前端工程化

Django 自带模板引擎,写个 {% for post in posts %} 确实方便。但问题是——2024 年了,谁还纯用 Django 模板搞前端?

我们 PM 要求“要有动态交互、要加载动画、要响应式”,我第一反应是:上 Vue/React 啊!但领导说:“MVP 别搞复杂,先用 HTMX 或者 Alpine.js 对付一下。”

我试了 HTMX,确实香:几行 HTML 属性就能实现 AJAX 请求,不用写一行 JS。比如点击按钮加载更多文章:

<button hx-get="/more-posts/" hx-target="#post-list">Load More</button>
<div id="post-list">
  <!-- posts here -->
</div>

后端只需要返回一段 HTML 片段即可。省去了前后端分离的 CORS、Token、打包部署一堆事,特别适合内部工具。

但如果你真要上 React/Vue,建议直接前后端分离:Django 只做 API,前端用 Vite 构建,部署时 Nginx 分发。不过这就超出“第一个网站”的范畴了,下次再聊。


数据库设计:别让 ORM 成为你的性能黑洞

Django ORM 很爽,.filter().exclude().order_by() 链式调用像写 SQL 一样自然。但爽过头就会翻车

我在列表页写了这么一句:

posts = Post.objects.all()
for post in posts:
    print(post.author.username)  # 触发 N+1 查询!

结果页面加载慢得像在等双十一快递。打开 Django Debug Toolbar 一看:100 条帖子,发了 101 条 SQL

解决方法?select_relatedprefetch_related

posts = Post.objects.select_related('author').all()  # 一条 JOIN 搞定

生产环境务必开启 DEBUG=False 并配置日志监控 SQL 查询次数!否则运维半夜打电话说“数据库 CPU 100%”,锅就是你的。

另外,别用 SQLite 上生产!虽然开发时方便,但并发一高就锁表。我们测试环境用 PostgreSQL,Docker 一键启动:

# docker-compose.yml
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: mysite
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: secret
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

部署上线:从“本地能跑”到“线上炸了”

本地 python manage.py runserver 跑得好好的,一部署到服务器就 502。原因?Django 自带的开发服务器不能用于生产!

正确的姿势是:Gunicorn + Nginx

# 安装 Gunicorn
pip install gunicorn

# 启动(注意 --bind 0.0.0.0)
gunicorn mysite.wsgi:application --bind 0.0.0.0:8000

Nginx 配置反向代理:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /static/ {
        alias /path/to/your/staticfiles/;
    }
}

静态文件别忘了收集

python manage.py collectstatic

还有 SECRET_KEY、DEBUG、ALLOWED_HOSTS 这些配置,千万别硬编码在 settings.py 里!用环境变量:

# settings.py
import os

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'fallback-for-dev')
DEBUG = os.environ.get('DJANGO_DEBUG', 'True') == 'True'
ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', 'localhost').split(',')

我们用 Docker + GitHub Actions 自动部署,每次 push 到 main 分支就触发构建。CI/CD 流水线里加个 python manage.py check --deploy,能提前发现很多配置问题


为什么没用 Go?资源与工具的权衡

说到这儿,肯定有人问:“既然你会 Go,为啥不直接用 Gin/Echo 搞个 API + 前端?”

答案很简单:资源有限,时间更有限

  • Go 要自己写 JWT 认证、权限控制、Admin 后台
  • Django 开箱即用 django.contrib.admin,5 分钟就能有个后台
  • 团队里有会 Python 的同事,Go 只有我一个人会
  • PM 明确要求“下周演示”,Deadline 是第一生产力

Django 的优势不是技术多先进,而是生态成熟、工具链完整、开发效率极高。对于非高并发、非低延迟的业务场景(比如内部系统、CMS、管理后台),它依然是王者。

当然,如果你要做高性能 API 网关、实时通信、微服务,Go 依然是我的首选。技术选型不是比谁更酷,而是看谁更能帮你在 deadline 前活着交付


总结:Django 教会我的事

折腾两周后,我的第一个 Django 网站终于上线了。虽然只是一个简单的博客后台,但它让我重新理解了“全栈”的重量。

  • 别迷信“简单”:Django 降低的是样板代码,不是架构思考。数据库设计、API 设计、安全防护,一样都不能少。
  • 工具链决定效率:VSCode + Django 插件 + Debug Toolbar + Docker,这套组合拳让我少走了 80% 的弯路。
  • 前端不是附属品:哪怕只是内部系统,用户体验也直接影响使用意愿。HTMX 这类轻量方案值得尝试。
  • Go 和 Python 不是对立:它们是不同场景下的最优解。会 Go 的程序员学 Django,反而能带来更严谨的工程思维。

最后,给正在踩坑的你说句实在话:别怕报错,每个 ImportError 背后都是成长的机会。当你终于看到那个绿色的 “It worked!” 页面时,所有的深夜 debug 都值了。

对了,我现在已经在用 Django + Celery + Redis 做异步任务了……PM 说下个版本要加邮件通知。救命,我想回 Go 的怀抱了 😭


附:我的开发资源清单

类型 工具/库 用途
IDE VSCode + Python Extension Pack 代码高亮、调试、虚拟环境识别
数据库 PostgreSQL + pgAdmin 生产级关系型数据库
调试 Django Debug Toolbar 实时查看 SQL、缓存、请求耗时
部署 Gunicorn + Nginx + Docker 标准生产部署方案
前端增强 HTMX + Alpine.js 无 JS 框架实现动态交互
CI/CD GitHub Actions 自动测试、构建、部署

记住:工具是死的,人是活的。用最适合当前项目的那一套,别被技术洁癖绑架。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝