Django入门教程:搭建你的第一个Python网站(顺便拯救一下我的跳槽简历)
上周五晚上十点半,我正瘫在工位上盯着电脑屏幕发呆。外面下着上海特有的那种黏糊糊的春雨,楼下的便利店还亮着灯,但我知道今天是回不去了——产品经理临时加了个需求,说要在下周三上线一个“内部工具原型”,用来展示给投资人看。而这个“原型”,居然要能注册、登录、上传文件、还能实时预览……我说大哥,这不就是个完整的小型 SaaS 产品吗?
最离谱的是,团队里后端只剩我和另一个同事,他还在搞 Go 微服务拆分,忙得连饭都顾不上吃。我一咬牙,干脆自己上吧。反正最近不是在考虑跳槽嘛?正好练练手,把简历上的“熟悉 Web 开发”写得更硬气一点。
于是,我打开了尘封已久的 Python 虚拟环境,敲下了那行熟悉的命令:
pip install django
没错,今天这篇《Django入门教程》,不是为了教学而教学,而是我在真实 deadline 压力下,从零搭建一个可用网站的血泪复盘。如果你也像我一样,坐标上海、租房住在公司附近、白天被业务需求追着跑、晚上还得偷偷学 AI 技术防身,那这篇文章或许能帮你少走点弯路。
为什么是 Django?而不是 Flask 或 FastAPI?
说实话,我一开始犹豫过要不要用 Flask。轻量、灵活、写起来爽,社区资源也多。但转念一想——我现在缺的是时间,不是自由度。Django 自带 Admin 后台、用户认证、ORM、安全防护(CSRF、XSS 防护等),开箱即用。对于一个要快速出原型、又不想半夜被线上漏洞叫醒的打工人来说,Django 真的是救命稻草。
而且,你猜怎么着?最近投的几家公司在面试题挑战里,居然有 Django 相关的题目!比如:“Django 的 MVT 架构和传统 MVC 有什么区别?”、“如何优化 Django ORM 查询性能?”——这些题要是答不上来,简历直接进回收站。所以,学 Django 不仅是为了项目,更是为了活下去。
第一步:创建你的第一个 Django 项目
先别急着写代码,咱们先把环境搭起来。我在 macOS 上操作,但 Linux/Windows 差不多。
# 创建虚拟环境(强烈建议!别污染全局)
python -m venv mysite_env
source mysite_env/bin/activate # Windows 用 mysite_env\Scripts\activate
# 安装 Django
pip install django
# 创建项目
django-admin startproject mysite
cd mysite
# 启动开发服务器
python manage.py runserver
打开浏览器,访问 http://127.0.0.1:8000,看到那个经典的火箭图标了吗?恭喜你,已经跑起来了!
吐槽时间:我们公司运维非要所有服务监听
0.0.0.0,结果本地测试时不小心把开发服务器暴露到内网,被安全扫描抓了个正着。运维大哥在群里@我:“兄弟,下次记得改runserver 0.0.0.0:8000之前先问问防火墙同不同意。” 我:……好的哥。
第二步:理解 Django 的“约定优于配置”
Django 最让人又爱又恨的一点,就是它有一大堆默认约定。比如:
- 所有应用(App)放在项目根目录下
- 模板默认在
templates/文件夹 - 静态文件在
static/ - 数据库配置在
settings.py的DATABASES里
刚开始会觉得“好死板”,但用熟了你会发现——这种一致性让团队协作变得超顺畅。新来的实习生只要看过 Django 文档,基本就能看懂项目结构,不用问“这个配置在哪改”。
我们来创建一个叫 blog 的应用(虽然我做的不是博客,但例子总得接地气):
python manage.py startapp blog
然后在 mysite/settings.py 里注册它:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ... 其他默认项
'blog', # ← 加这一行
]
踩坑提醒:有一次我忘了注册 App,结果模型迁移死活不生效,查了两小时才发现是
INSTALLED_APPS漏了。当时真的想砸键盘。
第三步:设计模型(Model)——数据库的灵魂
假设我们要做一个简单的文章发布系统。每篇文章有标题、内容、作者、发布时间。
在 blog/models.py 里写:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
注意这里用了 ForeignKey 关联 Django 内置的 User 模型——这意味着我们直接复用 Django 的用户系统,不用自己写注册登录逻辑!省下至少两天时间。
然后生成并执行迁移:
python manage.py makemigrations
python manage.py migrate
生产经验:在正式项目中,永远不要用 SQLite!我们公司一开始图快用了 SQLite,结果上线后并发一高就锁表。后来迁移到 PostgreSQL,配合连接池,稳如老狗。所以
settings.py里记得改:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypass',
'HOST': 'localhost',
'PORT': '5432',
}
}
第四步:写视图(View)和模板(Template)
Django 支持函数视图(FBV)和类视图(CBV)。新手建议从 FBV 开始,逻辑更直观。
在 blog/views.py:
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all().order_by('-created_at')
return render(request, 'blog/post_list.html', {'posts': posts})
然后创建模板文件 blog/templates/blog/post_list.html:
<!DOCTYPE html>
<html>
<head>
<title>我的博客</title>
</head>
<body>
<h1>文章列表</h1>
{% for post in posts %}
<div>
<h2>{{ post.title }}</h2>
<p>作者:{{ post.author.username }}</p>
<p>{{ post.content|truncatewords:30 }}</p>
</div>
{% endfor %}
</body>
</html>
最后,在 blog/urls.py(如果没有就新建)里配置路由:
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
]
并在主 urls.py 中包含它:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
]
现在访问 http://127.0.0.1:8000/blog/,应该能看到文章列表了!
第五步:用 Admin 后台管理数据(老板最爱的功能)
Django 的 Admin 是神器。只需两步:
- 在
blog/admin.py注册模型:
from django.contrib import admin
from .models import Post
admin.site.register(Post)
- 创建超级用户:
python manage.py createsuperuser
然后访问 /admin,用刚才创建的账号登录,就能增删改查 Post 了。产品经理看到这个界面,眼睛都亮了:“这后台能直接用吧?”
真实场景:上次双11大促前,运营小姐姐半夜打电话问我能不能改商品价格。我说你去 Admin 改就行,她愣了三秒:“啊?这么简单?” —— 这就是 Django 的魅力。
性能与部署:别让玩具变炸弹
本地跑得欢,上线就崩盘,这是很多新手的噩梦。分享几个生产环境的经验:
1. 静态文件处理
开发时 Django 自动服务静态文件,但生产环境必须用 Nginx。否则每次请求都要走 Python 进程,CPU 直接拉满。
2. 数据库查询优化
避免 N+1 查询!比如上面的 post_list,如果模板里访问 post.author.email,就会为每个 post 单独查一次 user 表。
解决方法:用 select_related:
posts = Post.objects.select_related('author').all()
3. 缓存
对不常变的数据(比如首页文章列表),加上缓存:
from django.core.cache import cache
def post_list(request):
posts = cache.get('post_list')
if posts is None:
posts = list(Post.objects.select_related('author').all())
cache.set('post_list', posts, 60 * 15) # 缓存15分钟
return render(request, 'blog/post_list.html', {'posts': posts})
和 GitHub 集成:让你的代码有家可归
写完代码当然要 push 到 GitHub!不仅是为了备份,更是为了:
- 展示项目给面试官看
- 参与开源社区(比如提 PR 修复 Django 文档 typo)
- 用 GitHub Actions 做 CI/CD
我的习惯是:
git init
git add .
git commit -m "feat: initial Django blog app"
git remote add origin https://github.com/yourname/mysite.git
git push -u origin main
顺带一提,GitHub 上有很多优质的 Django 学习资源,比如 awesome-django 这个 repo,收录了各种插件、教程、最佳实践。我就是靠它避开了不少坑。
Django vs Go:不是对立,而是互补
有朋友问我:“现在 Go 这么火,还学 Django 干啥?”
我的看法是:技术栈没有高低,只有合不合适。
- 如果你要做高性能微服务、CLI 工具、云原生组件,Go 确实香。
- 但如果你要做快速迭代的 Web 应用、需要丰富生态(用户系统、后台管理、REST API)、团队熟悉 Python,Django 依然是王者。
我们公司现在的架构就是:前端 + Django(主应用) + Go(高性能计算模块)。两者通过 gRPC 或 REST 通信,各司其职。
所以别被“Go 取代 Python”的营销号洗脑了。作为开发者,多掌握一门框架,就多一条退路——尤其是在考虑跳槽的时候。
写在最后:技术是手段,不是目的
折腾完这个小项目,已经是凌晨两点。雨停了,楼下便利店的灯也灭了。我把代码推到 GitHub,截图发到朋友圈配文:“Deadline 是第一生产力。”
其实我知道,这个网站离上线还差得远:没写单元测试、没配 HTTPS、没做权限控制……但在跳槽迷茫期,能亲手把一个想法变成可运行的网站,这种成就感,比刷一百道 LeetCode 都管用。
如果你也在犹豫要不要换工作,不妨先动手做个东西。简历上的“项目经验”,永远比“精通 XXX”更有说服力。
Django 不是银弹,但它足够快、足够稳、足够成熟。在这个 AI 炒作满天飞的时代,能静下心来写一个完整的 Web 应用,本身就是一种稀缺能力。
好了,我去睡了。明天还要改产品经理的新需求——他说投资人觉得“上传文件”不够酷,要加个 AI 自动生成摘要的功能……
(完)
附:常用资源清单
| 类型 | 推荐 |
|---|---|
| 官方文档 | docs.djangoproject.com(必读!) |
| 入门教程 | Django Girls Tutorial(超友好) |
| GitHub 示例 | django/django, wsvincent/djangoforbeginners |
| 面试题挑战 | LeetCode “Django” 标签、牛客网后端面经 |
| 生产部署 | 使用 Gunicorn + Nginx + PostgreSQL + Redis |
本文代码已开源:github.com/yourname/mysite(假装有链接)
欢迎 Star & Fork,顺便看看我其他关于 AI 的学习笔记 😉

评论 0