Django入门教程:搭建你的第一个Python网站
县城的初夏,窗外蝉鸣吵得人脑壳疼。我坐在老家的书桌前,戴着降噪耳机放着《孤勇者》——别笑,代码写累了听这个真提神——一边在 VS Code 里敲着 Python,一边盘算着要不要把简历更新一下。
我在这家远程办公的小公司干了三年多,说是“后端开发”,其实天天在 Java 的世界里打转:Spring Boot、MyBatis、Redis、Kafka……一套组合拳打下来,连做梦都在 debug。但最近公司项目趋于稳定,老板又开始画饼说要“拥抱多语言生态”,顺手丢给我一个任务:“你不是一直对性能优化感兴趣嘛?试试用 Python 搞个轻量级管理后台,看看能不能替代一部分老旧的 Java 服务。”
说实话,一开始我是拒绝的。毕竟 Java 虽然啰嗦,但稳啊!线上跑了一年半没崩过(除了那次产品经理半夜改需求导致 OOM)。但转念一想,现在招聘市场上,会 Python + Django 的岗位越来越多,尤其是中小厂和 SaaS 初创公司,Django 几乎成了标配。我刷 BOSS 直聘时发现,不少 JD 都写着“熟悉 Django 优先”,甚至有些面试题挑战直接让你现场写个 CRUD 接口。
行吧,那就学!反正县城生活成本低,房租一个月 600,晚上还能陪爸妈散步,时间有的是。
为什么选 Django?而不是 Flask 或 FastAPI?
我知道很多人会说:“现在都 2024 年了,谁还用 Django 啊?Flask 够轻,FastAPI 性能炸裂!”
这话没错,但对我这种“小镇做题家”来说,上手速度 > 架构优雅 > 性能极致。Django 自带 ORM、Admin、Auth、Migrations,开箱即用,不用自己拼轮子。上周五晚上加班到 11 点,我还被运维大哥吐槽:“你们 Java 项目部署文档写了 50 页,光环境变量就 30 个,能不能学学人家 Python 社区,一行 python manage.py runserver 就跑起来了?”
虽然有点扎心,但确实是事实。Django 的“约定优于配置”哲学,特别适合快速验证想法。而且它的 Admin 后台,简直是给懒人准备的神器——数据库建好,注册一下模型,一个功能完整的后台就出来了,连前端都不用写。
当然,我也知道 Django 在高并发场景下不如 FastAPI,但在我们这种日活几千的小系统里,先跑起来,再优化,才是务实之道。更何况,Django 3.0+ 已经原生支持 ASGI,配合 Gunicorn + Uvicorn,性能也完全够用。
动手:从零搭建一个“资源分享站”
为了模拟真实场景,我决定做一个极简的“技术资源分享平台”——用户可以上传学习资料(比如 PDF、视频链接),其他人可以点赞、评论。这玩意儿听着简单,但涉及用户认证、文件存储、API 设计、数据库关系,正好练手。
第一步:环境准备(别跳过,血泪教训)
# 创建虚拟环境(县城网速慢,pip install 经常 timeout)
python -m venv django-env
source django-env/bin/activate # Linux/Mac
# django-env\Scripts\activate # Windows
pip install django pillow # pillow 用于处理图片缩略图
踩坑记录:第一次没装
pillow,上传图片时报错The _imaging C module is not installed,当时真的想砸电脑。后来才知道 Django 的 ImageField 依赖它。
第二步:创建项目 & 应用
django-admin startproject resource_hub
cd resource_hub
python manage.py startapp resources
项目结构如下:
resource_hub/
├── manage.py
├── resource_hub/ # 项目配置
│ ├── settings.py
│ ├── urls.py
│ └── ...
└── resources/ # 我们的应用
├── models.py
├── views.py
└── ...
第三步:设计数据库模型(重点!性能优化从这里开始)
既然是资源分享站,核心模型有三个:用户(User,用 Django 自带的)、资源(Resource)、评论(Comment)。
# resources/models.py
from django.db import models
from django.contrib.auth.models import User
class Resource(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
file = models.FileField(upload_to='resources/') # 文件存储路径
url = models.URLField(blank=True) # 如果是在线资源
uploader = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name='liked_resources', blank=True)
class Meta:
indexes = [
models.Index(fields=['created_at']), # 按时间排序常用
models.Index(fields=['uploader']), # 用户主页查自己的资源
]
ordering = ['-created_at']
class Comment(models.Model):
resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=['resource', 'created_at']), # 评论按资源+时间查
]
为什么加索引?
去年双11期间,我们 Java 项目因为没给 order_by 字段加索引,导致列表页查询超时,DB CPU 打满。运维差点把我挂墙上。从此我养成了“凡查询必索引”的习惯。
另外,likes 用 ManyToManyField 而不是单独建表,是因为 Django 会自动创建中间表,省事。但如果未来点赞量爆炸(比如百万级),可能要考虑用 Redis 缓存计数,避免 JOIN 太重。
第四步:配置静态文件 & 媒体文件(生产环境必看)
开发时,Django 可以直接 serve 静态文件,但生产环境绝对不能这么干!
我在 settings.py 里做了区分:
# settings.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# 开发环境
if DEBUG:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
else:
# 生产环境建议用云存储(比如阿里云 OSS)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = 'my-resource-hub'
MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/'
县城程序员的无奈:家里宽带上传只有 20Mbps,测试文件上传时等得想哭。后来干脆用 MinIO 搭了个本地 S3 兼容服务,速度快多了。
第五步:写视图 & API(RESTful 风格)
为了方便前后端分离(虽然这次我用 Django Template 快速出页面),我还是按 RESTful 设计接口:
| 方法 | 路径 | 功能 |
|---|---|---|
| GET | /resources/ | 获取资源列表 |
| POST | /resources/ | 创建新资源 |
| GET | /resources/{id}/ | 获取单个资源详情 |
| POST | /resources/{id}/like/ | 点赞 |
关键代码:
# resources/views.py
from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
import json
@login_required
def resource_list(request):
if request.method == 'GET':
resources = Resource.objects.prefetch_related('likes').all()
data = [{
'id': r.id,
'title': r.title,
'likes_count': r.likes.count(),
'uploader': r.uploader.username,
} for r in resources]
return JsonResponse(data, safe=False)
elif request.method == 'POST':
data = json.loads(request.body)
resource = Resource.objects.create(
title=data['title'],
description=data.get('description', ''),
uploader=request.user,
url=data.get('url', '')
)
return JsonResponse({'id': resource.id}, status=201)
@login_required
def like_resource(request, resource_id):
resource = get_object_or_404(Resource, id=resource_id)
if request.user in resource.likes.all():
resource.likes.remove(request.user)
liked = False
else:
resource.likes.add(request.user)
liked = True
return JsonResponse({'liked': liked, 'count': resource.likes.count()})
注意:prefetch_related('likes') 是为了 N+1 查询问题。如果不加,每条资源都要查一次点赞用户,100 条资源就是 101 次 SQL!我们 Java 项目就吃过这亏,JPA 的 @OneToMany 默认不 fetch,结果列表页慢如蜗牛。
第六步:跑起来!(以及那些年踩过的坑)
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser # 创建管理员,后面进 Admin 用
python manage.py runserver
访问 http://127.0.0.1:8000/admin,用刚才创建的账号登录,就能看到自动生成的后台!添加几个资源试试,简直不要太爽。
但别高兴太早——当你把 DEBUG=False 并部署到 Nginx 时,各种 404、500 就来了。
我总结了三条生产部署 checklist:
- 收集静态文件:
python manage.py collectstatic - 配置 ALLOWED_HOSTS:必须加上你的域名或 IP,否则 500 错误
- 数据库连接池:用
dj-database-url+psycopg2,别用默认 SQLite
和 Java 对比:Django 的“快”与“痛”
作为一个 Java 老兵,我不得不说,Django 在开发效率上碾压 Spring Boot。同样一个 CRUD 功能:
| 维度 | Java (Spring Boot) | Django |
|---|---|---|
| 代码量 | Controller + Service + Mapper + Entity + DTO ≈ 200 行 | models.py + views.py ≈ 50 行 |
| 启动速度 | 5~10 秒 | < 1 秒 |
| 学习曲线 | 高(注解、AOP、事务传播) | 低(约定大于配置) |
| 生态工具 | Maven/Gradle 依赖复杂 | pip + virtualenv 简单直接 |
| 类型安全 | 强类型,编译期报错 | 动态类型,运行时报错 |
但 Django 也有痛点:
- 异步支持弱:虽然 ASGI 可用,但 ORM 还是同步的,高并发 I/O 密集型场景不如 FastAPI
- 调试体验一般:PyCharm 断点还行,但远不如 IDEA 对 Java 的深度集成
- 大型项目结构混乱:没有像 Spring 那样清晰的分层规范,容易写出“面条代码”
写在最后:这和求职有什么关系?
其实我折腾这个小项目,不只是为了完成老板的任务。最近在准备跳槽,刷了不少面试题挑战,发现很多公司(尤其是 To B SaaS 公司)都在用 Django 做内部系统、数据平台、甚至核心业务。
比如某家做 HR SaaS 的公司,一面就让我现场写个“员工信息管理”接口,要求支持分页、搜索、导出 Excel。用 Django 的 Admin + 自定义 Action,半小时搞定。而如果用 Java,光配 MyBatis Plus + PageHelper 就得折腾半天。
更重要的是,掌握多语言思维,能让你在面试中脱颖而出。当面试官问“你怎么看待不同框架的选型?”时,你可以结合 Java 和 Python 的实战经验,说出:“对于快速迭代的 MVP 产品,Django 的开发效率无可替代;但对于高并发交易系统,Java 的稳定性更可靠。”——这种回答,比背八股文强多了。
此刻,窗外天色已暗,我妈在喊我吃晚饭。我把代码 push 到 GitHub,顺手在 README 里加了一句:
“一个县城程序员的 Django 初体验。代码很糙,但能跑。如果你也在小城市远程工作,欢迎 star 交流。”
或许,这就是我们这些“小镇做题家”的浪漫:不在大厂卷 P9,也能用代码改变自己的一亩三分地。
对了,项目地址:github.com/yourname/resource-hub(假装存在)
下次聊聊怎么用 Django + Celery 做异步任务,解决文件上传阻塞的问题。毕竟,性能优化,永无止境。
—— 一个边听《孤勇者》边写代码的县城后端

评论 0