从零开始,用 Django 搭建我的第一个 Python 网站
开篇:为什么是 Django?

我是一名在互联网公司工作的后端开发工程师,主要负责服务端架构设计和系统搭建。说起第一次使用 Django 搭建网站的经历,我还挺感慨的。那会儿刚入职一家创业公司,业务要得急,时间又紧张,技术选型上不能有太多试错空间。
当时我们准备快速上线一个内部使用的任务管理后台,用来支撑市场团队和产品团队的协作流程。这个项目不需要太复杂的功能,但要有完整的用户体系、权限控制、数据可视化能力,同时要求开发周期短、后期易维护。
摆在面前的选择有两个:Flask 和 Django。
Flask 更轻量,灵活性高,适合小项目或定制化程度高的场景。但缺点也很明显:很多功能需要自己写轮子,比如用户认证、后台界面这些。Django 就不一样了,它是“自带电池”的全栈框架,内置了 admin 后台、ORM、用户系统、模板引擎等等,开箱即用,能大幅缩短初期开发时间。
最后我们果断选择了 Django,事实也证明这步选对了。这篇文章就来分享一下我当时是如何一步步搭起这个后台系统的,以及在这个过程中踩过的坑和学到的经验。
问题描述:时间紧,压力大,新人难上手

项目的难点其实不在于功能多复杂,而是在于资源有限 + 时间紧迫 + 团队新人多。
- 时间:产品经理只给了两周时间原型+前后端实现;
- 人力:前端是我拉了一个实习生临时帮忙切页面,后端就我一个人撑着;
- 经验不足:虽然我个人对 Python 相对熟悉,但之前都是做一些脚本或数据处理的工作,Web 框架这块还是第一次实战,尤其是 Django。
最头疼的是当时完全没有头绪,不知道如何组织结构,也不清楚如何利用好 Django 提供的那些便捷工具。如果一切从零造轮子,肯定来不及。
所以必须找到一套既能快速启动,又能为未来扩展留有余地的开发方式。
解决方案:Django 的模块化架构 + 内置 Admin 系统

技术选型理由:
- 开发效率优先:Django 自带 ORM 可以快速映射模型,Admin 管理后台可以自动生成基本的CRUD操作,这对快速验证业务逻辑非常友好;
- 可维护性考虑:Django 遵循 MVT 设计模式(Model-View-Template),代码结构清晰,便于后期多人协作;
- 社区生态成熟:插件丰富,比如 django-crispy-forms、django-guardian、rest_framework 等,满足不同阶段的扩展需求;
- 部署成本低:配合 Gunicorn + Nginx 的组合部署,在生产环境中表现稳定,且容易调试。
我们最终决定采用以下基础技术栈:
- Web 框架:Django(3.2)
- 数据库:PostgreSQL
- 前端:Bootstrap + jQuery(少量 Vue.js 用于组件化)
- 用户权限:Django 自带的 auth 模块 + Group 分组控制
- 部署工具:Docker + Gunicorn + Nginx
代码实践:搭建第一步 —— 创建你的第一个项目


先来看看最基本的项目初始化步骤。
# 安装 django
pip install django
# 创建项目
django-admin startproject task_dashboard
# 进入目录并运行服务器
cd task_dashboard
python manage.py runserver
这时访问 http://localhost:8000,你应该能看到 Django 默认的欢迎页。
接下来创建我们的核心 app:
python manage.py startapp tasks
在 settings.py 中注册该 app:
INSTALLED_APPS = [
...
'tasks',
]
然后定义第一个模型类,假设我们要记录每个任务的信息:
# tasks/models.py
from django.db import models
from django.contrib.auth.models import User
class Task(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True, null=True)
assignee = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
due_date = models.DateField()
status_choices = (
('pending', 'Pending'),
('in_progress', 'In Progress'),
('completed', 'Completed')
)
status = models.CharField(max_length=20, choices=status_choices, default='pending')
def __str__(self):
return self.title
接着生成数据库迁移文件,并执行:
python manage.py makemigrations
python manage.py migrate
别忘了创建超级管理员账号:
python manage.py createsuperuser
这时候你可以登录 http://localhost:8000/admin 查看自动为我们生成的任务管理界面了!
是不是很神奇?一行数据接口都没写,就已经有了可视化的 CRUD 功能。
接口设计:REST API 快速接入前端
随着前端同学完成页面设计,我们需要提供 RESTful 风格的接口进行数据交互。于是引入了 Django REST Framework。
安装:
pip install djangorestframework
添加到 INSTALLED_APPS 中:
INSTALLED_APPS = [
...
'rest_framework',
]
编写简单的视图和序列化器:
# tasks/serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
# tasks/views.py
from rest_framework import viewsets
from .models import Task
from .serializers import TaskSerializer
class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all()
serializer_class = TaskSerializer
配置路由:
# tasks/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import TaskViewSet
router = DefaultRouter()
router.register(r'tasks', TaskViewSet)
urlpatterns = [
path('', include(router.urls)),
]
再全局导入到主 urls.py:
# task_dashboard/urls.py
from django.urls import path, include
urlpatterns = [
path('api/', include('tasks.urls')),
]
现在访问 /api/tasks/ 就可以看到 JSON 格式的任务列表了,甚至还有网页版的 API 浏览器!再也不用手写 View 返回 JsonResponse 了。
踩坑经验:真实开发中遇到的问题及解决方案
1. ORM 查询性能问题
早期我为了简单方便,直接用了 .all() 获取全部任务:
Task.objects.all()
结果上线后发现数据库查询特别慢,特别是当任务数量变多之后。
后来通过分析日志,发现没有加任何过滤条件的情况下,每次请求都会拉取全表数据,而且没有分页机制。
解决办法:
- 使用 Django REST Framework 的分页组件;
- 对外暴露的接口加上查询参数支持;
- 关键字段增加索引(如 assignee、due_date);
示例:
from rest_framework.pagination import PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
class TaskViewSet(viewsets.ModelViewSet):
pagination_class = StandardResultsSetPagination
...
同时,我还在 PostgreSQL 表中为经常查询的字段添加了索引:
CREATE INDEX idx_assignee ON tasks_task (assignee_id);
大大提升了查询效率。
2. 权限控制没想清楚,上线后权限混乱
我们一开始用的是默认的 Django auth 用户体系,但在分配任务时,出现了权限越权的问题:A 组用户能看到 B 组用户的任务数据。
这个问题是因为我们在写 API 的时候并没有限制只能查询当前用户的数据。
解决方案:
- 在 TaskViewSet 中重写
get_queryset方法,限制用户只能查看自己的任务; - 引入
django-guardian实现对象级权限控制(更细粒度的权限管理); - 配合 Group 机制,实现角色划分和权限隔离。
代码简化示例如下:
def get_queryset(self):
user = self.request.user
if user.is_superuser:
return Task.objects.all()
return Task.objects.filter(assignee=user)
3. 生产环境部署踩坑
本地测试没问题,一上生产就报错:静态文件加载失败,500 错误满天飞。
排查了一圈才发现:
- 静态资源路径配置不对:Django 的 STATIC_ROOT 和 STATICFILES_DIRS 需要区分清楚;
- Gunicorn 启动命令错误:忘记加
--chdir到项目根目录; - Nginx 配置漏掉了 media 文件的代理;
- PostgreSQL 版本与开发机不一致导致部分字段不兼容。
最后统一用 Docker 打包部署,解决了版本差异的问题,整个流程标准化了不少。
效果总结:两周完成 MVP 并上线生产环境
项目按时上线后,市场和产品团队反馈良好,UI 简洁直观、后台操作流畅。虽然功能不算复杂,但后续基于这个框架,我们又陆续加了通知中心、消息订阅机制、权限分级等高级功能,系统变得越来越完整。
最关键的是:
- 新人接手快,Django 的结构让他们很快理解项目逻辑;
- 扩展能力强,很多功能可以直接通过集成第三方 App 实现;
- 部署运维稳定,几乎没有出过大的故障;
- 性能优化到位,响应时间一直保持在合理范围内。
经验分享:给初学者的几点建议
如果你也在学习 Django 或者刚开始用它做项目,我这里给你几个实用建议:
1. 合理使用内置功能,避免重复造轮子
比如 admin 后台、auth 系统、form 表单验证、DRF、中间件等,都是经过社区打磨多年的优质组件,不要轻易舍弃它们去自己实现类似功能。
2. 注重数据库设计,提前规划索引和表结构
尤其是在项目中后期,一旦表结构定下来,调整起来成本很高。建议初期就画 E-R 图,明确表之间的关系。
3. 善用中间件和信号(signals)解耦逻辑
比如记录用户行为日志、触发异步任务等都可以用 signals 实现,让核心业务逻辑保持干净。
4. 学会用缓存提升性能
Django 提供了 cache 框架,对于频繁读取的接口可以加缓存,减少 DB 压力。
5. 考虑容器化部署,提高交付效率
像我们后来用的 Docker + Kubernetes 方案,不仅保证环境一致性,还可以通过 CI/CD 实现自动化部署,节省大量沟通和调试成本。
写在最后:Django 是个值得深入学习的好工具
说实话,刚开始接触 Django 的时候我也觉得它有点“笨重”,不如 Flask 灵活。但真正投入进去之后,你会发现它的成熟性和稳定性远胜于其他轻量级框架。
特别是在团队协作、系统维护、长期迭代等方面,Django 给你提供的不仅仅是功能上的便利,更是一种工程思维和规范——而这才是作为开发者最应该掌握的能力。
希望这篇文章能帮你少走弯路,顺利搭建起你的第一个 Python Web 项目。如果你有任何问题或者遇到了什么奇怪的 bug,也欢迎留言交流,我们一起成长。
共勉。

评论 0