从产品经理到后端:我用Django搭了个能跑的网站
去年在成都一家中型 SaaS 公司做产品经理时,我天天跟开发“打架”——他们嫌 PRD 写得太细,我嫌接口文档太糙。后来实在忍不了了,心想:“要不我自己写个原型?”于是真就买了本《Python Web 开发实战》,开始啃 Django。没想到这一啃,直接让我转岗成了全栈(伪)工程师。
今天这篇不是教科书式的“Hello World”,而是从一个前 PM、现斜杠青年的角度,聊聊如何用 Django 搭建一个真正可维护、有扩展性的第一个网站。毕竟,写代码不只是为了跑起来,还得让三个月后的自己和接手的同事不至于想砸电脑。
为啥选 Django?而不是 Java Spring Boot?
我知道,很多公司后端还是 Java 的天下。我们之前那个项目就是 Spring Cloud + MyBatis,部署一次得求运维大哥半天。而我在成都这种生活节奏慢的地方,更倾向于“快点搞定,早点喝茶”。Django 自带 ORM、Admin、用户认证、路由系统,开箱即用,特别适合 MVP(最小可行产品)快速验证。
而且,作为一个曾经被前端同事吐槽“你这接口字段命名像火星文”的前 PM,我深知接口设计的一致性和文档清晰度有多重要。Django REST Framework(DRF)在这方面简直是救星——自动生成 API 文档、序列化器强制规范输入输出,连测试都内置了。
当然,Java 系生态稳如老狗,适合高并发金融场景。但如果你只是想做个内部工具、爬虫展示平台或者个人博客,Django 能让你少掉 80% 的头发。
需求来了:做个爬虫数据展示页
上周五晚上,运营小姐姐突然微信我:“能不能把咱们爬的豆瓣电影数据,弄个网页看看?现在全在 Excel 里,打开都卡。”
我一看表,晚上 9 点。行吧,反正周末无事,不如练练手。
需求很简单:
- 后端:存电影名、评分、上映年份
- 前端:列表展示,支持按年份筛选
- 额外:加个“导出 CSV”按钮(PM 的执念)
但作为转技术的人,我脑子里第一反应不是“怎么实现”,而是:
- 数据结构怎么设计才不容易改?
- 接口要不要分页?未来数据量大了怎么办?
- 前端用原生 JS 还是上 Vue?算了,先用原生,别搞复杂。
架构设计:小项目也要有“骨架”
很多人学 Django 就 python manage.py startapp 然后往 views 里堆逻辑。但我在看开源项目源码时学到一点:哪怕只有三个页面,也要分层清晰。
我的目录结构如下:
movies/
├── models.py # 数据模型
├ └── serializers.py # DRF 序列化器
├── views.py # 视图逻辑(尽量薄)
├── urls.py # 路由
└── static/
└── js/
└── main.js # 原生 JavaScript 处理筛选和导出
数据库设计:别怕预留字段
# models.py
from django.db import models
class Movie(models.Model):
title = models.CharField(max_length=200, verbose_name="电影名")
rating = models.FloatField(verbose_name="评分")
year = models.IntegerField(verbose_name="上映年份")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-year'] # 默认按年份倒序
indexes = [
models.Index(fields=['year']), # 加索引!未来数据多时不卡死
]
这里特意加了 created_at 和数据库索引。虽然现在只有 100 条数据,但好习惯要从第一天养成。上次我们线上库没加索引,结果双11期间一个查询拖垮了整个 DB,DBA 差点把我挂树上。
接口设计:DRF 让前后端不再吵架
# serializers.py
from rest_framework import serializers
from .models import Movie
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = ['id', 'title', 'rating', 'year']
# views.py
from rest_framework import generics
from .models import Movie
from .serializers import MovieSerializer
class MovieListView(generics.ListAPIView):
serializer_class = MovieSerializer
def get_queryset(self):
queryset = Movie.objects.all()
year = self.request.query_params.get('year')
if year:
queryset = queryset.filter(year=year)
return queryset
看,筛选逻辑放在 get_queryset 里,清晰又可测。前端只需要拼 URL 参数 ?year=2023 就行,不用猜接口格式。再也不用听前端抱怨:“你们后端字段一会儿叫 movieName 一会儿叫 film_title!”
前端交互:原生 JS 足够,别过度工程
很多人一上来就想用 React/Vue,但这个需求真的需要吗?我用 50 行原生 JavaScript 搞定了:
// static/js/main.js
document.getElementById('filter-btn').addEventListener('click', async () => {
const year = document.getElementById('year-input').value;
const url = year ? `/api/movies/?year=${year}` : '/api/movies/';
const res = await fetch(url);
const movies = await res.json();
// 渲染表格...
});
document.getElementById('export-btn').addEventListener('click', () => {
// 直接跳转到 Django 提供的 CSV 导出接口
window.location.href = '/movies/export/';
});
简单、直接、没有构建步骤。等哪天需求复杂了,再考虑上框架也不迟。技术选型要看场景,不是越新越好。
生产环境踩坑:别在本地爽完就提交
本地跑得飞起,推到测试环境直接 500?这事儿我干过。
几个关键配置必须改:
# settings.py (生产环境)
DEBUG = False # 别留 True 上线!
ALLOWED_HOSTS = ['your-domain.com'] # 否则 400 Bad Request
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # 收集静态文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
# 别把密码写死!
}
}
另外,记得运行 collectstatic。有次我忘了,上线后 CSS 全没了,页面丑得像 90 年代网吧首页,被测试截图发群里嘲笑了一周。
性能对比:Django vs “你以为的慢”
有人总说 Python 慢,Django 不适合生产。但真相是:对于 I/O 密集型应用(比如 Web),瓶颈从来不在语言本身,而在数据库和架构。
我用 Locust 做了个简单压测(100 并发,列表接口):
| 方案 | 平均响应时间 | 错误率 |
|---|---|---|
| 未加索引 | 1200ms | 5% |
加了 year 索引 |
80ms | 0% |
| 加了 Redis 缓存(缓存热门年份) | 35ms | 0% |
看,优化空间大着呢。Django 本身足够快,关键是你怎么用。
最后:为什么我推荐新手从 Django 开始?
- 快速反馈:改一行代码,刷新就能看到效果,学习曲线平缓。
- 强制规范:MTV 架构逼你分层,不像 Flask 那样容易写出意大利面条代码。
- 生态成熟:Admin 后台、用户系统、权限控制,全都有。
- 适合全栈思维:从前端请求到数据库查询,你能串起来理解整个链路。
当然,如果你目标是进大厂写高并发交易系统,那 Java + Spring Cloud 仍是主流。但如果你像我一样,在成都的小团队里既要画原型又要写代码,Django 能让你在下午 4 点准时下班去喝盖碗茶。
对了,那个豆瓣电影展示页,运营小姐姐昨天说:“比 Excel 好用多了!” —— 虽然她不知道背后我加了多少索引、写了多少测试,但那一刻,我觉得转行真值了。
代码已开源在 GitHub(搜索 “django-movie-demo”),欢迎提 Issue 吐槽。毕竟,程序员的浪漫,就是让世界少一个 Excel 文件。

评论 0