搭建第一个 Django 网站:从零到部署上线的实战经历
引言:为什么要分享这个话题?

还记得我刚加入互联网公司做后端开发的时候,接到的第一个任务就是快速搭建一个内部管理系统。当时我虽然在学校里学过 Python,但真正动手做一个完整的网站还是头一回。老板给的时间不多,项目又急,我只能硬着头皮上。
那会儿,团队选用了 Django 作为技术栈。说实话,我当时对框架了解不深,只知道它“全栈”,文档多、社区活跃。抱着边学边做的心态,我一头扎进了 Django 的世界。整个过程跌跌撞撞,踩了不少坑,但也让我从零开始建立起了完整的后端开发思维模型。
今天我想借这篇文章,把我的亲身经历分享出来。如果你是 Python 初学者,或者正准备入门 Web 开发,希望通过这篇实战教程,帮你少走弯路。我会从项目背景讲起,再到具体实现、踩过的坑、最后部署上线,全部基于我在真实工作中遇到的问题和解决方案。
项目背景:为什么我们需要这样一个网站?

我们当时要做的是一个内部运营后台,用来管理公司即将上线的一个新产品的活动配置。功能相对简单:支持管理员登录,上传活动信息、管理用户数据、查看数据统计等。
听起来不难,但要求一周内上线,而且要能处理一定的并发访问量。这种情况下,Django 显得非常合适——自带认证系统、ORM 支持、Admin 后台开箱即用,还能快速构建 RESTful API。
选择 Django 的另一个原因是,团队之前做过类似的项目,有经验可循,文档完善,出了问题也能找到参考案例。这对我们这种时间紧、压力大的项目来说至关重要。
遇到的挑战:新手常遇到的问题 + 实际工作中的痛点

挑战 1:如何组织项目结构?
刚开始的时候,我对 manage.py、settings.py、app 的概念还很模糊。官方文档说“一个项目包含多个应用(app)”,但我完全不知道怎么划分这些 app。例如:
- 用户管理?
- 活动配置?
- 数据统计?
- 日志记录?
一开始我把所有功能都写在一个 app 里,后来随着需求增加,代码越来越乱,根本不好维护。这个问题在实际工作中很常见,尤其是当团队协作时,结构不合理会影响效率。
挑战 2:数据库设计不合理导致后期修改困难
初期为了快,我直接按需求字段建表,没考虑索引、外键关联、数据冗余等问题。比如一个“活动”对应多个“奖品”,我就直接把奖品内容存成 JSON 字符串放到活动表里。结果后面要做数据分析的时候发现没法高效查询,性能瓶颈很快暴露了出来。
挑战 3:REST API 接口设计混乱,版本迭代难
我第一次尝试自己写 API 的时候,URL 路由随便写,POST 参数也是一股脑全传过来,完全没有遵循什么规范。后来接口改动频繁,前端抱怨不断,因为每次改都需要重新对接。这时候才意识到良好的接口设计多么重要。
挑战 4:本地测试没问题,上线却各种错误
最头疼的是部署阶段。我们在 Ubuntu 上跑 Gunicorn+Nginx,一开始静态文件找不到、权限问题一堆,还有模板路径设置错,导致页面加载失败。日志系统也没有合理配置,出错只能靠 print 打印调试,效率极低。
解决方案:我是怎么一步步解决这些问题的?
结构规划:模块化设计原则
后来我按照功能拆分 app,每个模块职责明确。最终的结构大致如下:
myproject/
├── config/ # 项目配置文件
│ └── settings.py # 分开发、测试、生产环境
├── users/
├── activities/
├── prizes/
├── analytics/
└── manage.py
这样做有两个好处:
- 职责清晰,哪个功能在哪部分一目了然;
- 便于扩展和维护,后续加新功能可以只关注对应的 app,不会互相干扰。
数据库设计优化:规范化与索引提升查询效率
活动和奖品之间本来是“一对多”的关系,我把它改为两个表:
class Activity(models.Model):
name = models.CharField(max_length=200)
start_time = models.DateTimeField()
end_time = models.DateTimeField()
class Prize(models.Model):
activity = models.ForeignKey(Activity, on_delete=models.CASCADE, related_name='prizes')
name = models.CharField(max_length=100)
quantity = models.PositiveIntegerField()
image_url = models.URLField()
这样就可以通过 ORM 查询某个活动的所有奖品:
activity.prizes.all()
同时为经常查询的字段加上索引:
class Meta:
indexes = [
models.Index(fields=['start_time']),
models.Index(fields=['end_time'])
]
接口设计统一化:引入 Django REST Framework (DRF)
最初我自己写视图函数返回 JSON,后来发现 DRF 太好用了。它不仅能自动生成序列化器,还能自动根据 Model 创建接口,大大提升了开发效率。
示例代码如下:
from rest_framework import viewsets
from .models import Activity
from .serializers import ActivitySerializer
class ActivityViewSet(viewsets.ModelViewSet):
queryset = Activity.objects.all()
serializer_class = ActivitySerializer
路由注册也简单:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from activities.views import ActivityViewSet
router = DefaultRouter()
router.register(r'activities', ActivityViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
从此接口风格统一,前后端沟通也顺畅多了。
代码实践:关键代码片段和配置示例

项目目录结构建议
如前所述,推荐使用类似下面的结构:
myproject/
├── config/
│ ├── __init__.py
│ ├── settings_dev.py
│ ├── settings_prod.py
│ └── urls.py
├── apps/
│ ├── users/
│ ├── activities/
│ └── ...
└── manage.py
使用 virtualenv 管理依赖(真实场景经验)
很多同学喜欢全局安装包,但在多人协作或部署时容易出问题。我们都是通过 virtualenv 来隔离依赖:
python3 -m venv venv
source venv/bin/activate
pip install django djangorestframework
然后将依赖保存到 requirements.txt:
pip freeze > requirements.txt
settings 配置分离(非常重要!)
很多人会在 settings.py 里一股脑写死所有配置,但不同环境差异很大。我们通常会做成:
settings_base.py公共配置settings_dev.py开发环境settings_prod.py生产环境
然后根据运行环境载入不同的配置:
# 启动命令示例
python manage.py runserver --settings=config.settings_dev
gunicorn myproject.wsgi --env DJANGO_SETTINGS_MODULE=config.settings_prod
静态文件和 media 设置(踩坑重点)
在本地开发时:
# settings_dev.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
部署到线上时,需要用 Nginx 来托管静态资源,否则 Django 不会处理。所以我们配置如下:
# settings_prod.py
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
然后收集静态文件:
python manage.py collectstatic
踩坑经验:那些年我踩过的坑
坑 1:Migrations 冲突,本地和服务器不一致
有时候手动删了 migrations 文件或者数据库表,导致服务器报错:
django.db.migrations.exceptions.InconsistentMigrationHistory
解决办法:
python manage.py migrate --fake-initial
但这不是长期方案。最好的做法是保持本地和线上迁移一致,避免手动操作。
坑 2:Gunicorn 启动失败,提示权限不足
这是因为 gunicorn 进程没有权限访问某些文件,比如上传目录。解决方式是设置合适的权限:
sudo chown -R www-data:www-data /path/to/media
sudo chmod -R 755 /path/to/media
另外,Nginx 和 Gunicorn 的 log 文件也要定期清理,否则磁盘会被占满。
坑 3:DEBUG=False 之后,静态文件无法访问
这是新手常见的问题。Django 在生产环境下不负责静态文件服务,需要通过 Nginx 或 CDN 来代理。
配置 Nginx 示例:
location /static/ {
alias /path/to/static/;
}
location /media/ {
alias /path/to/media/;
}
效果总结:上线后的表现如何?
这个项目最终按时上线,顺利支撑了初期几百个用户的访问量。通过监控工具看 QPS 一度达到 10 左右,响应时间控制在 100ms 以内。几个星期后活动结束,系统稳定运行无故障。
更棒的是,这套结构在后面的项目中被复用多次,节省了大量重复开发的时间。团队成员接手时也更容易理解代码结构。
经验分享:写给正在学习 Django 的你
如果你刚开始学习 Django,不要被它的“大而全”吓住。它确实强大,但也足够灵活。以下是我总结的一些实用建议:
1. 项目结构要清晰,提前设计好模块
别一开始就写业务逻辑,先想清楚每个 app 是干嘛的,模块之间怎么交互。这比后期重构轻松太多。
2. 学会使用 DRF,API 规范必须统一
不管是前后端分离项目,还是移动端调用,统一的接口设计能大幅提升效率。DRF 就是最好的帮手。
3. 不要在 settings 里写死配置,学会分环境管理
这点在团队协作和 CI/CD 中尤为重要。你可以结合 Docker + .env 文件来管理敏感信息。
4. 多看看源码,深入理解框架机制
比如了解一下中间件是怎么运作的,ORM 是如何生成 SQL 的。知其然还要知其所以然。
5. 不要怕踩坑,解决问题本身就是成长
每一个 bug、每一条错误日志,背后都有原因。搞懂它们的过程,也是你成为合格后端工程师的关键。
最后的话:关于 Django 的未来和学习路线
Django 依然保持着稳健的更新节奏,社区活跃,生态丰富。现在越来越多的微服务架构也开始结合 Django+DRF 来提供 REST 接口。
如果你已经掌握了基本的 Web 开发流程,建议继续深入以下几个方向:
- Django Channels(WebSocket 支持)
- Celery 异步任务调度
- Postgres 特性深度使用(JSONB、全文搜索)
- 性能调优(缓存、数据库索引、查询优化)
- 自动化部署(CI/CD 流程、Docker 化)
Django 可以做大型项目,也可以轻量化嵌套进其它架构中。关键是你要掌握核心原理,并能在工程实践中灵活运用。
希望这篇来自一线开发者的真实经历,能够对你有所启发。如果还有任何疑问或者想交流心得,欢迎留言评论,我们一起成长!
文章作者:一位在互联网公司搬砖多年的后端工程师
技术栈:Python/Django/PostgreSQL/Nginx/Golang/Linux/CICD
个人感悟:写代码就像搭积木,结构越清晰,后期越轻松

评论 0