Django初体验:从零搭建一个能跑的Python网站
上周五凌晨两点,我正窝在工位上和一个诡异的Redis缓存穿透问题死磕,突然想起自己还在刷LeetCode准备跳槽。这时候产品经理又发来消息:“能不能先搞个简单的管理后台出来?下周就要演示了。”我盯着屏幕上满屏的Go微服务日志,叹了口气——得,又是熟悉的“既要、又要、还要”。
作为一个常年用Vim写代码、连IDE都懒得装的老后端,我对前端向来是敬而远之。但这次躲不掉了:领导说“综合能力要提升”,暗示跳槽前得有点全栈经验。行吧,那就拿Django练手,毕竟Python生态里它最省事。
为什么选Django而不是Flask?
其实我一开始想用Flask,轻量、灵活,符合我们服务端开发的审美。但转念一想:我现在每天被线上事故追着跑,哪有精力从零搭轮子?Django自带Admin、ORM、用户认证、CSRF防护……一套全家桶,正好适合我这种只想快速交付的打工人。
而且说实话,我们团队最近在评估技术栈收敛。虽然主力是Go写的微服务,但内部工具链用Python更高效。Django这种“约定优于配置”的框架,反而能减少团队沟通成本——毕竟没人想半夜三点还在争论路由怎么写。
创建项目:比想象中快得多
打开终端(没错,我还在用iTerm2 + Vim),几行命令搞定:
pip install django
django-admin startproject mysite
cd mysite
python manage.py runserver
浏览器打开 http://127.0 .0.1:8000,经典的火箭图标出现。那一刻我居然有点感动——多久没见到这么顺利的Hello World了?上个月用某个国产框架,光配环境就折腾了两天。
不过别高兴太早。生产环境可不能直接用runserver。我立马在settings.py里加了几个关键配置:
# 生产环境必须关掉
DEBUG = False
# 允许的域名
ALLOWED_HOSTS = ['your-domain.com']
# 数据库换成PostgreSQL(别再用SQLite上生产了!)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': 'db.internal',
'PORT': '5432',
}
}
这里有个血泪教训:去年双11前,测试环境用SQLite跑得好好的,上线后并发一高直接锁表。运维老哥半夜打电话骂我:“你当PostgreSQL是玩具吗?” 从那以后,本地开发我也强制用Docker起PostgreSQL。
写个博客应用:从前端到后端串起来
为了演示“综合”能力,我决定做个极简博客系统。需求很简单:
- 用户能发布文章
- 文章列表页展示标题和摘要
- 点进去看全文
模型设计:别小看这个环节
很多新手直接开写视图,但我作为服务端老油条,第一反应是数据库设计。在models.py里定义:
from django.db import models
from django.contrib.auth.models import User
class Article(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)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
indexes = [
models.Index(fields=['created_at']),
models.Index(fields=['author', '-created_at']),
]
注意两点:
- 外键关联User:直接复用Django内置的用户系统,省得自己搞注册登录
- 手动加索引:别依赖Django自动建的索引,查询性能会崩。我们线上就吃过亏——一个没加联合索引的订单表,高峰期QPS直接打满CPU
生成迁移文件并执行:
python manage.py makemigrations
python manage.py migrate
顺手创建个超级用户:
python manage.py createsuperuser
然后访问 /admin,用刚才的账号登录——Wow!一个功能完整的后台管理界面自动生成了。产品经理要是看到这个,估计能笑醒。
视图与模板:前端部分怎么搞?
我知道很多后端讨厌写HTML,但Django的模板系统其实挺克制。我在views.py里写了个简单视图:
from django.shortcuts import render
from .models import Article
def article_list(request):
articles = Article.objects.select_related('author').order_by('-created_at')[:10]
return render(request, 'blog/list.html', {'articles': articles})
关键点:select_related 避免N+1查询。这可是性能优化的基本功——上次review代码时,实习生没加这个,测试环境查100篇文章触发了101次SQL,被我当场抓包。
模板文件list.html放在templates/blog/目录下:
<!DOCTYPE html>
<html>
<head>
<title>我的博客</title>
<!-- 别笑,这就是我的前端水平 -->
<style>
.article { margin-bottom: 20px; padding: 10px; border-left: 3px solid #eee; }
</style>
</head>
<body>
<h1>最新文章</h1>
{% for article in articles %}
<div class="article">
<h2>{{ article.title }}</h2>
<p>作者: {{ article.author.username }} | {{ article.created_at|date:"Y-m-d H:i" }}</p>
<p>{{ article.content|truncatewords:30 }}</p>
</div>
{% empty %}
<p>暂无文章</p>
{% endfor %}
</body>
</html>
虽然丑,但能跑。前端同事看了可能会摇头,但对内部工具来说够用了。真要上用户产品,我肯定甩给专业前端——毕竟我们的KPI不是拼UI。
性能考量:别让Django变“单机版”
很多人说Django慢,其实是用错了姿势。分享几个生产经验:
1. 静态文件交给Nginx
Django处理静态文件效率低,必须在部署时用Nginx代理:
location /static/ {
alias /path/to/staticfiles/;
expires 30d;
}
2. 数据库连接池
默认的DB连接每次请求新建,高并发下会耗尽连接数。我们用django-db-geventpool(配合Gunicorn)解决。
3. 缓存策略
对于文章详情页,加上简单的cache:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 缓存15分钟
def article_detail(request, pk):
# ...
性能对比(本地压测)
| 配置 | QPS (wrk -t4 -c100 -d30s) |
|---|---|
| 默认Django | 220 |
| + Gunicorn (4 workers) | 850 |
| + Nginx静态文件分离 | 920 |
| + Redis缓存热点数据 | 1450 |
可见,合理配置下Django完全能扛住内部系统流量。当然,如果是高并发C端产品,我们还是会用Go重写核心服务——但Django做MVP或管理后台,效率无敌。
部署上线:踩坑实录
最后一步最致命。我用Docker打包,结果遇到经典问题:时区不对。
Django默认UTC时间,但用户看到的是本地时间。解决方案:
# settings.py
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True # 必须设为True才能正确转换
另一个坑:SECRET_KEY泄露。千万别把密钥写死在代码里!我们用环境变量:
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
CI/CD脚本里注入密钥,Git仓库干干净净。这都是被安全审计逼出来的习惯——去年因为密钥提交到GitHub,被罚写了三千字检讨。
Django vs Go:我的真实想法
写完这个小项目,我反而更理解团队的技术选型了。Django适合:
- 快速验证业务想法
- 内部管理后台
- 原型开发
而Go适合:
- 高并发API服务
- 微服务核心逻辑
- 对启动时间和内存敏感的场景
两者根本不是对手,而是互补。我们现在的架构就是:Django做运营后台 + Go微服务集群 + Vue前端。各司其职,谁也别鄙视谁。
结语:打工人的时间管理术
凌晨三点,终于把Django项目跑通了。看了看LeetCode还没刷,又瞄了眼招聘软件上那些“精通Django”的JD,苦笑一下。
其实学Django不是为了转全栈,而是让自己在跳槽时多一张底牌。后端工程师的核心能力永远是系统设计和性能优化,框架只是工具。但在这个卷成麻花的时代,多会一个技能,简历就能多过一轮筛选。
所以啊,别纠结“该不该学前端”。当你能用Django半小时搭出一个可用系统,用Go写出高性能服务,用Vim流畅编码——你早就超越了90%的“纯后端”。
(完)
P.S. 刚才测试同学发消息说新需求来了……算了,先去改bug,Django教程就写到这儿吧。反正也没人看我博客,都是给自己留的笔记 😅

评论 0