从零开始,用 Django 搭建我的第一个网站:一次真实的后端开发初体验
初识 Django:为什么是我人生中第一个 Web 项目选了它?

去年我刚入行做后端开发的时候,公司正好接了一个小项目:搭建一个内部使用的任务管理系统,用来记录日常开发中的待办事项、Bug 跟踪和协作信息。虽然系统不大,但要求快速上线,并且后续可能需要扩展更多功能。
作为新人的我被分到了这个项目里,leader给的建议是:“试试用 Django 吧,上手快,适合这种中小型项目。”当时我对 Python 的理解还停留在写一些简单脚本的程度,更别提用框架来搞 Web 开发了。不过出于好奇和挑战心理,我还是决定尝试用 Django 来完成这次任务。
这一试,开启了我真正的后端开发之路,也让我彻底爱上这个“笨重但强大”的框架。
项目背景与挑战:一个看似简单的后台管理平台

我们的任务管理系统本质上是一个基于角色的 CRUD 系统,主要功能包括:
- 用户登录与权限控制(管理员/普通用户)
- 任务创建、查看、修改、删除
- 任务状态流转(未开始 / 进行中 / 已完成)
- 简单的通知系统(比如某人领取了新任务)
表面上看,这似乎是个再简单不过的项目。但实际上,我第一次独立负责完整模块时才发现:需求看起来越简单,细节反而越容易翻车。
具体来说,我遇到的问题包括:
- 数据库设计混乱:一开始没想好表结构,导致后面频繁改动 model,migration 都快弄炸了;
- 接口安全与性能问题:比如没有限制请求频率,被人一刷,服务直接挂掉;
- 前后端分离不彻底:Django 模板引擎 + 原生 JS 撸了个页面,结果前端吐槽渲染太慢;
- 部署踩坑:本地跑得好好的,生产环境各种路径错误、静态文件找不到……
这些问题其实都是新手常见病,幸运的是,在一次次调试和复盘中,我慢慢摸索出了门道。
技术方案与实现思路:Django 是如何帮我们解决问题的?

我们的技术栈最终确定如下:
- 后端:Python + Django
- 数据库:PostgreSQL
- 接口:DRF(Django REST framework)
- 前端:Vue.js 单页应用(SPA),后期改造成前后端分离架构)
- 部署:Nginx + Gunicorn + Supervisor + Let's Encrypt HTTPS
整体结构设计
整个系统采用典型的 MVC 架构,核心模型有三个:
# models.py
from django.db import models
from django.contrib.auth.models import User
class Task(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
status = models.CharField(
max_length=20,
choices=[('pending', 'Pending'), ('in_progress', 'In Progress'), ('done', 'Done')],
default='pending'
)
assigned_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
class Comment(models.Model):
task = models.ForeignKey(Task, related_name='comments', on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Notification(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
message = models.CharField(max_length=255)
is_read = models.BooleanField(default=False)
这是我后来重构过的一套 model,最开始的设计非常乱,甚至没有考虑索引和外键约束,惨痛教训啊!
接口设计与权限控制
使用 DRF 提供 API 接口时,我特别注意了权限和接口安全性。比如在任务详情接口中,我们这样处理权限校验:
# views.py
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from .models import Task
from .serializers import TaskSerializer
class TaskViewSet(viewsets.ModelViewSet):
serializer_class = TaskSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
# 只返回当前用户有权访问的任务
return Task.objects.filter(assigned_to=self.request.user)
def perform_create(self, serializer):
# 创建任务时自动绑定创建者为当前用户
serializer.save(created_by=self.request.user)
这套机制确保了每个用户只能看到自己的任务,不会互相干扰。而针对 admin 用户,则单独做了权限判断。
代码实践与关键配置分享

接下来是一些我认为对新人特别有用的配置片段和技巧。
settings.py 中的关键设置项
# 安全设置
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY') # 生产环境不要硬编码
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
# 数据库设置(生产使用 PostgreSQL)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT', '5432'),
}
}
# 静态文件设置(部署时关键)
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Django REST Framework 设置
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
]
}
部署必备:Gunicorn + Nginx 配置
我们最终选择了 Gunicorn 作为 WSGI 服务器,配合 Nginx 做反向代理和静态文件托管。
Gunicorn systemd 服务配置示例:
# /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=deployer
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/path/to/your.sock yourproject.wsgi:application
[Install]
WantedBy=multi-user.target
Nginx 配置片段:
server {
listen 80;
server_name www.yourdomain.com;
location / {
proxy_pass http://unix:/path/to/your.sock:/;
include proxy_params;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /path/to/staticfiles/;
}
location /media/ {
alias /path/to/media/;
}
}
这些配置帮助我们在生产环境中稳定运行,而且能有效减少资源浪费。
踩坑经验分享:那些年我走过的弯路
1. Migrations 弄得满地鸡毛
刚开始不懂 makemigrations 和 migrate 的区别,经常自己手动去改 migration 文件或者误删 migrations 目录。后果就是数据库和代码严重不同步,最后不得不手动清空数据库重建 😣
建议:永远不要手动删除或修改 migration 文件!可以用 --fake 参数来修复历史问题。
2. 多人协作时的 model 冲突
有一次我和同事同时改了同一个 model 的某个字段类型,合并代码之后发现各自的 migration 冲突,导致 migrate 出错。后来学乖了,每次合并之前先同步 migrations。
建议:团队合作时一定要及时沟通 model 修改情况,合并前做好测试。
3. 忘记加缓存,接口卡到爆
早期接口没有任何缓存策略,结果有一次前端用了个列表组件疯狂调用 /api/tasks,每秒几十次请求直接把服务器干趴下了。
解决方法:用 DRF 提供的缓存装饰器,对高频读取的接口加上缓存逻辑:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
@method_decorator(cache_page(60 * 5), name='dispatch') # 缓存5分钟
class TaskListView(generics.ListAPIView):
...
项目上线后的效果与收益总结
项目上线后,虽然只是个小系统,但确实带来了不少实际价值:
- 团队成员可以清晰追踪任务进度,告别“你是不是还在做那件事”的尴尬提问;
- Bug 报告有了统一入口,减少了邮件和钉钉消息的噪音;
- 我个人通过这个项目掌握了 Django 的基本使用、DRF 接口设计、部署流程,以及团队协作中的一些规范意识。
更重要的是,我真正体会到了“从 0 到 1”打造一个完整产品的感觉,那种看着自己写的代码在线上跑起来、被人每天使用,真的超级有成就感!
给读者的建议与注意事项

如果你也是刚开始学习 Django 或者 Python 后端开发,以下几点可能会帮到你:
别怕“笨”,多动手
Django 功能很多很庞杂,但别想着一开始就全掌握,先跑起来再说。哪怕是只做个 Hello World 页面,都能带来很大启发。重视数据库设计
model 是整个系统的灵魂,设计不好会拖垮后续所有工作。推荐提前画 ER 图,多问前辈意见。尽早引入测试和文档
写代码的同时顺便写点单元测试和接口文档,不仅能帮你发现问题,也能让其他人更容易接手你的项目。学会查官方文档和社区资源
Django 官方文档写得非常棒,而且社区活跃,几乎你能遇到的问题都有现成的解决方案。善用 Stack Overflow、GitHub issues 和 Reddit。别迷信“轻量级框架”
很多人说 FastAPI 更快、Flask 更灵活,没错,但对于中小项目而言,Django 的成熟生态和开箱即用的功能,真的是生产力神器。尤其是当你一个人开发的时候,Django admin、ORM、auth 系统这些节省的时间成本是无价的。
写在最后:Django 教会我的不只是写代码
这段开发经历让我明白,写代码只是工程的一部分,更重要的还有:
- 理解业务需求背后的本质;
- 设计出易维护、可扩展的架构;
- 在压力下快速定位并解决问题;
- 学会和他人高效协作。
Django 像一位严格的老师,它让你必须认真对待每一个决策,也给你足够多的自由去发挥创造力。希望这篇文章能给刚刚起步的你一点方向和信心。
愿你在编程的路上越走越远,愿每一个深夜敲代码的你,都有光陪着。

评论 0