用 Django 快速搭建你的第一个 Python 网站:一个全栈开发者的实战分享
引言:为什么我会选择 Django 来入门 Web 开发?

如果你是一个刚接触 Web 开发的 Python 爱好者,面对琳琅满目的框架,比如 Flask、FastAPI、Tornado,可能会不知道从哪下手。我当年也是这样,在试过几个轻量级框架后,最终选择了 Django。
为什么?因为 Django 给我一种“一站式解决方案”的感觉。它自带 ORM、模板引擎、后台管理、认证系统……几乎你想到的功能都有现成的轮子。而且社区活跃、文档完整,非常适合新手快速上手,并且能够直接用来做实际项目。
这篇文章,我想跟你聊聊我第一次使用 Django 搭建网站的经历——不是那种“Hello World”级别的教程,而是结合我在实际工作中遇到的问题和踩过的坑来写的一次真实体验分享。
项目背景:公司内部要搭一个员工信息管理系统

去年年初,我在一家中型互联网公司做后端开发实习生。某天 team lead 找我,说需要我们组尽快上线一个员工信息管理系统(CMS),用于人事部门录入员工信息、导出报表、做一些基础查询。
当时我们的技术栈是 Python 主流生态,前端用的是 Vue.js,但 CMS 这块不需要太复杂交互,只需要一个简单的管理后台就行。于是团队决定让我尝试用 Django 搭建后台服务,并集成一个简易的管理界面。
这个项目的挑战在于:
- 时间紧,只有 3 天时间完成
- 需要支持登录权限控制、数据展示、导出 Excel
- 需要可扩展,后续可能接入 API 接口供前端调用
技术选型与整体架构设计

后端结构
采用经典的 Django 架构,即 MVC 模式的变形:MTV(Model - Template - View)。
- Model:定义数据库结构
- View:处理逻辑和请求
- Template:页面渲染
- Admin:Django 自带的后台管理系统,方便 HR 直接操作数据
同时为了接口化需求,我们引入了 djangorestframework 来提供 RESTful API。
数据库设计
考虑到员工信息主要字段包括:姓名、身份证号、入职时间、职位、所属部门、薪资等级等,我设计了如下的模型结构:
from django.db import models
from django.contrib.auth.models import User
class Department(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True)
position = models.CharField(max_length=100)
join_date = models.DateField()
salary = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return self.user.username
这里需要注意几点:
- 使用 Django 内置的 User 模型进行用户管理,避免重复造轮子
- 员工信息通过 OneToOneField 关联,既节省空间又方便维护
- 部门字段用了 SET_NULL 而不是 CASCADE,避免误删关联数据
实践过程:从创建项目到功能落地
初始化项目
先安装 Django:
pip install django
然后创建项目:
django-admin startproject employee_cms
cd employee_cms
python manage.py startapp employees
注册应用:
在 settings.py 的 INSTALLED_APPS 中加入:
'employees',
'django.contrib.humanize',
'rest_framework',
运行迁移:
python manage.py migrate
创建超级管理员账号:
python manage.py createsuperuser
接下来就可以访问 admin 页面 /admin 登录后台了。
编写 Model 和 Admin 管理界面
在 employees/admin.py 中注册模型:
from django.contrib import admin
from .models import Department, Employee
@admin.register(Department)
class DepartmentAdmin(admin.ModelAdmin):
list_display = ('name', )
search_fields = ('name', )
@admin.register(Employee)
class EmployeeAdmin(admin.ModelAdmin):
list_display = ('user', 'department', 'position', 'join_date')
list_filter = ('department', 'join_date')
search_fields = ('user__username', 'position')
此时刷新 admin 页面,就已经可以新增部门、员工信息了。
展示页面 View + Template
我们要做一个列表页展示所有员工信息。首先在 views.py 编写:
from django.shortcuts import render
from .models import Employee
def employee_list(request):
employees = Employee.objects.all().select_related('department', 'user')
return render(request, 'employees/list.html', {'employees': employees})
然后在 urls.py 添加路由:
from django.urls import path
from . import views
urlpatterns = [
path('', views.employee_list, name='employee_list'),
]
最后在 templates/employees/list.html 文件里写 HTML 渲染:
{% extends "base.html" %}
{% block content %}
<h1>员工列表</h1>
<table>
<thead>
<tr>
<th>用户名</th>
<th>部门</th>
<th>职位</th>
<th>入职日期</th>
</tr>
</thead>
<tbody>
{% for emp in employees %}
<tr>
<td>{{ emp.user.username }}</td>
<td>{{ emp.department.name }}</td>
<td>{{ emp.position }}</td>
<td>{{ emp.join_date|date:"Y-m-d" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
这部分代码看似简单,但在实际部署中也遇到了不少小插曲……
踩坑经验分享
问题一:静态资源无法加载,页面样式乱掉了
错误现象:HTML 页面引用了 CSS 或 JS 文件,但是浏览器显示 404。
原因分析:Django 在开发模式下自动处理静态文件,但在生产环境必须手动配置静态文件路径。
解决方法:
在 settings.py 中添加:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # 部署时 collectstatic 收集目录
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
然后运行收集命令:
python manage.py collectstatic
并在 Nginx 配置中指向 static 目录:
location /static/ {
alias /path/to/staticfiles/;
}
问题二:数据库查询效率低,加载员工列表特别慢
场景描述:当员工数量达到千级以上,页面打开开始变卡。
排查过程:我原本是这样写的查询语句:
Employee.objects.all()
结果 Django 默认只查主表字段,关联字段会逐一发起查询,导致出现“N+1 查询”问题。
优化方案:
使用 select_related 显式预加载关联数据:
Employee.objects.select_related('department', 'user').all()
进一步还可以用 values() 限制返回字段:
Employee.objects.select_related('department').values('id', 'user__username', 'department__name')
这一步让页面加载速度提升了 70% 以上。
问题三:Excel 导出功能卡死服务器
功能需求:点击“导出”按钮,下载一份包含员工信息的 Excel 文件。
实现方式:一开始我用 openpyxl 动态生成 Excel 并返回给客户端,看起来没问题。
隐患爆发:当数据量超过几千条,内存飙升、响应超时频繁发生。
优化建议:
改用流式处理,配合 HttpResponse 实时输出,避免一次性加载:
import openpyxl
from django.http import HttpResponse
def export_employees(request):
response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=employees.xlsx'
workbook = openpyxl.Workbook()
worksheet = workbook.active
worksheet.title = '员工信息'
columns = ['用户名', '部门', '职位', '入职日期']
row_num = 1
for col_num, column_title in enumerate(columns, 1):
worksheet.cell(row=row_num, column=col_num).value = column_title

employees = Employee.objects.select_related('department').values(
'user__username', 'department__name', 'position', 'join_date'
)
for emp in employees:
row_num += 1
worksheet.cell(row=row_num, column=1).value = emp['user__username']
worksheet.cell(row=row_num, column=2).value = emp['department__name']
worksheet.cell(row=row_num, column=3).value = emp['position']
worksheet.cell(row=row_num, column=4).value = str(emp['join_date'])
workbook.save(response)
return response
这种方式在大数据量下依旧稳定运行,也没有引发 OOM(内存溢出)。
效果总结与收获
虽然项目时间很紧张,但我们还是提前半天完成了任务。最终系统交付后被 HR 部门广泛使用,不仅简化了人工录入流程,还提供了清晰的人员统计报表。
从技术角度来说,这次项目让我深刻体会到 Django 的强大之处:
- 开发效率高:借助 admin 和内置 ORM,节省了大量开发时间
- 适合做内容管理系统:内置管理后台、权限系统完善
- 可拓展性强:能轻松接入 REST API,为未来前后端分离打下基础
- 性能优化有余地:通过 ORM 优化、缓存、分页等方式提升性能
一些经验和建议送给你
1. 不要怕“重”,Django 就是为你省事的
很多初学者看到 Django 提供这么多东西会觉得“笨重”,其实不然。这些组件在企业项目中都非常实用,尤其是自带的管理后台和权限系统,真的能节省很多时间。
2. 注意模板安全
不要在模板中执行复杂逻辑或写太多 Python 表达式,保持模板简洁,业务逻辑尽量放在 view 中。
3. 多用中间件和信号机制
Django 提供了很多钩子函数,比如信号(signal),可以在保存模型时触发特定操作,比如记录日志、发送通知等。
4. 生产环境一定要配置静态文件 + 安全设置
记得启用 Gunicorn + Nginx,关闭 debug 模式,设置 allowed hosts,保护好你的站点。
5. 学会调试和日志跟踪
利用好 runserver 的调试工具,设置 logging 输出详细日志,在关键节点 print 出变量值也是一种“土办法”。
最后一句话:别怕犯错,多动手才能成长
说实话,我第一次写这个项目的时候也没少翻文档、问同事、网上搜资料。但现在回头看,正是那次项目让我对 Web 开发有了系统的理解,也让我的 Django 技术真正落地。
希望你也能像我一样,从一个小项目出发,逐渐成长为一名真正的全栈开发者。加油!
如果你对这个项目感兴趣,欢迎关注我的 GitHub,后续我会逐步开源整个系统的代码供大家参考学习 😊

评论 0