从0开始用Django搭建一个Python网站:踩坑、总结与实战经验分享
背景介绍:为什么选择Django?

还记得我刚入行那年,老板让我独立负责一个内部的用户管理系统。作为一个对后端还处于摸索阶段的小白,我在技术选型上犯了难。Java太重,Flask又觉得功能不够全。最后被一位前辈推荐了 Django ——“有ORM、开箱即用、社区活跃,适合新手但也不逊色于专业项目”。
抱着试一试的心态,我开始了第一次Django实践之旅。现在回头看,那次经历虽磕磕绊绊,但也让我彻底理解了一个Web项目的完整生命周期:从建模、路由配置,到模板渲染和部署上线。这篇文章我会用真实的开发场景,带你一起完成第一个Django网站,同时分享一些只有踩过才明白的坑。
我的第一个Django项目:员工信息管理系统

1. 项目背景和需求简述
这是一个简单的员工信息管理系统,主要功能包括:
- 员工基本信息录入(姓名、性别、电话、部门等)
- 查询列表展示
- 修改、删除功能
- 角色权限(管理员可以删改,普通用户只能查看)
听起来像是个练手项目,但在真实公司环境下,它承载着部门人员管理的基础数据支撑。我们没有太多预算去做前后端分离,因此采用Django默认的MTV架构快速搭建。
2. 初识Django:环境搭建的那些事
安装过程
pip install django
django-admin startproject emp_system
cd emp_system
python manage.py runserver
这三步是入门的第一道门槛。当时我在Mac上跑得没问题,结果换了台Windows设备就遇到各种问题:
- Python版本混用(3.7 vs 3.8)导致找不到模块
- 系统路径问题引发
manage.py运行失败 - 使用国内镜像时安装不完全,比如
whitenoise没成功
经验总结:
- 推荐使用虚拟环境(virtualenv/virtualenvwrapper/pipenv),防止版本冲突。
- Windows建议用WSL或PyCharm自带终端,减少命令兼容性问题。
- 首次不要着急自定义结构,老老实实走官方流程。
3. 设计模型:数据库才是核心
接下来就是设计我们的模型(models)。系统里最基础的表就是Employee,对应的字段如下:
class Employee(models.Model):
name = models.CharField(max_length=50)
gender = models.CharField(max_length=10, choices=[('男', '男'), ('女', '女')])
phone = models.CharField(max_length=20)
department = models.ForeignKey(Department, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
这里有几个我当时踩过的坑:
✅ ForeignKey命名习惯
最初我把外键写成:
department_id = models.ForeignKey(...)
后来发现Django本身会自动加 _id 的列名,直接写成 department = ForeignKey(...) 更清晰也符合规范。
✅ CharField的max_length设置
一开始我以为手机号固定是11位,结果上线后发现有国际号码、座机、甚至带分隔符的情况。于是修改为:
phone = models.CharField(max_length=20)
教训:永远别低估数据输入的复杂度。
4. URL路由怎么设计才合理?
URL路由设计虽然看着简单,但如果你一开始就随意安排,后面维护起来就像在理乱麻。
我的做法是按照业务模块划分app:
emp_system/
├── employee/ # 员工相关
├── department/ # 部门管理
└── users/ # 用户权限模块
每个app都有自己的urls.py文件,主路由通过include导入:
urlpatterns = [
path('admin/', admin.site.urls),
path('employee/', include('employee.urls')),
path('dept/', include('department.urls')),
]
经验分享:
- 不要所有路由都堆在全局urls.py中,不利于后期维护;
- 可以配合namespace避免name冲突,如:
path('', views.index, name='index')
然后在模板中引用:
{% url 'employee:index' %}
5. 模板渲染 vs 前后端分离?我的抉择
由于时间和资源限制,我没有选择Vue或React做前端,而是用了Django的模板引擎——这其实是很多中小型项目的真实选择。
举个例子:展示员工列表的页面,我们可以这样写视图函数:
def employee_list(request):
employees = Employee.objects.all()
return render(request, 'employee/list.html', {'employees': employees})
然后对应模板:
{% for e in employees %}
<tr>
<td>{{ e.name }}</td>
<td>{{ e.department.name }}</td>
...
</tr>
{% endfor %}
缺点我也尝到了:
- 页面刷新慢、用户体验差;
- 做条件搜索和分页不太方便;
- 样式维护起来麻烦。
但是它的优点也很明显:
- 开发效率高;
- 对静态文件依赖少;
- 调试更直观,错误能马上看到。
6. 权限控制怎么做?别用session瞎搞!
最初为了实现角色权限管理,我手动用session保存用户角色,每次请求都要判断session['role']是不是admin。结果很快出问题:
- Session失效时间不清不楚;
- 多人登录时容易串数据;
- 测试困难,调试时经常出现“明明不是admin却被允许访问”等问题。
后来我才真正意识到Django的auth系统有多强大。
from django.contrib.auth.decorators import login_required, permission_required
@login_required
@permission_required('employee.can_edit')
def edit_employee(request, eid):
...
这才是正道。
小技巧:
- 自定义权限可以在model里添加:
class Meta:
permissions = [
("can_edit", "Can Edit Employees"),
("can_delete", "Can Delete Employees")
]
- 用户组(Group)绑定权限,轻松分配不同角色。
7. 上线部署:你以为结束了,其实才刚开始
开发完之后以为万事大吉,结果在部署阶段遇到了不少坑。
第一次部署用的是Nginx + Gunicorn + MySQL(Ubuntu)
部署流程大致如下:
- 把项目上传到服务器;
- 安装Python、pip、MySQL、配置数据库;
- 设置Gunicorn启动;
- Nginx反向代理;
- 收集静态文件(collectstatic);
- 守护进程用systemd;
- HTTPS配置(Let’s Encrypt)
其中几个大坑:
❌ collectstatic没处理好
本地开发用的STATICFILES_DIRS,在生产必须设置STATIC_ROOT并执行:
python manage.py collectstatic --noinput
否则CSS、JS都不见了。
❌ DEBUG模式未关闭
上线前一定要记得:
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']
否则不仅暴露源码,还有安全隐患。
❌ 数据库配置疏忽
开发时用的SQLite,但上线必须换成PostgreSQL或MySQL,否则性能会崩。尤其是并发高的时候,SQLite根本撑不住。
总结:这个项目给我带来的收获

虽然是个小项目,但从头到尾折腾下来,我对整个Web项目的结构有了更加清晰的认识。
| 学到的关键点 | 实际应用 |
|---|---|
| MTV结构设计 | 所有Django项目通用框架 |
| ORM用法 | 减少原始SQL操作,提高可读性 |
| 路由规划 | 提升后期可扩展性和维护性 |
| 模板机制 | 快速构建静态网页内容 |
| 认证权限 | 后期几乎所有项目都要用到 |
| 部署上线 | 了解项目落地全流程 |
如果现在重新来一遍,我会这么做
✅ 项目结构提前规划
Django默认只有一个应用,但实际开发时应该按功能拆分成多个app,并统一用apps.py管理。比如:
emp_system/
├── apps/
│ ├── employee/
│ ├── dept/
│ └── accounts/
然后在settings.py里注册:
INSTALLED_APPS = [
'apps.employee',
'apps.dept',
'apps.accounts'
]
✅ 更早使用REST Framework
如果当时就知道DRF(Django REST framework),我现在可能已经做了前后端分离。不过对于初期快速验证产品形态来说,模板渲染依然是最快的方式之一。
✅ 日志和异常处理必须重视
Django的logging模块非常实用,尤其是在线上环境中排查错误。
比如在views.py加入try-catch捕获异常:
import logging
logger = logging.getLogger(__name__)
def some_view(request):
try:
...
except Exception as e:
logger.error(f"Error occurred: {e}")
return HttpResponseServerError("Internal Error")
并在settings中配置loggers:
LOGGING = {
...
}
写给刚起步的你几点建议
✅ 别害怕“笨方法”
作为新手,不要上来就追求什么微服务、异步加载、前后端分离。把基础打牢比什么都重要。先用Django模板、原生表单、内置Admin后台把这些“笨方法”吃透了,再考虑优化。
✅ 多写多练,别光看文档
文档确实重要,但你不写代码,根本体会不到什么叫“表单验证失败”、“CSRF token missing”或者“url reverse出错”。自己动手,才会发现问题。
✅ 善用Admin后台
Django Admin是一个强大的原型工具。很多时候产品经理提需求之前,你可以自己先用Admin快速搭个Demo出来演示,反馈更快。
✅ 学会用shell调试
python manage.py shell
这个命令简直神器。在交互式环境中可以直接测试Model查询、逻辑处理,比每次都跑server高效得多。
最后说一句:Django不止是工具,更是一种思考方式
Django教会我很多东西:比如什么时候该用信号机制(signal)而不是直接写逻辑、如何组织项目结构、以及最重要的——如何平衡效率和质量之间的矛盾。
现在的我已经不再只是一个用Django搭建小网站的人,而是在实际工作中参与过多模块、高并发、前后端联动的开发者。但每当回想起那段用Django写第一个网站的日子,内心依然充满感激。
愿你也在这条路上越走越稳,少踩坑,多成长。
如果你正在学习Django,或者刚刚准备迈入Web开发的大门,希望这篇文章能成为你的一盏灯,照亮前方的路。
如有任何疑问或需要交流经验,欢迎留言或私信。我们下篇见 😄

评论 0