从零开始用Django搭网站:一位后端程序员的成长之路
引言:为什么选择Django?

还记得两年前,我刚转行做后端开发的时候,公司安排了一个任务:在两周内,独立完成一个内部使用的资产管理系统。作为一个Python新手,我第一反应是——“这玩意儿怎么上手?有没有现成的框架?”这时候,前辈推荐了Django:“它功能齐全、文档完善,适合快速搭建功能完整的网站。”
说实话,当时我对这个框架几乎一无所知,只知道它是Python界的老牌Web框架。但随着项目的推进,我才真正体会到它的强大之处。这篇文章就想结合那次项目经历,聊聊我是如何从0到1用Django搭建第一个网站,以及其中踩过的那些坑和收获的经验。
项目背景:内部资产管理系统的需求

我们公司是一个中型互联网团队,之前很多资产管理流程都是靠Excel手工操作,效率低不说,还容易出错。于是领导决定做一个轻量级系统来统一管理电脑、服务器、网络设备等资源信息。
功能需求包括:
- 用户登录(权限控制)
- 资产分类与展示
- 添加/编辑/删除资产
- 模糊搜索和列表过滤
- 简单的数据统计(资产状态分布)
目标用户主要是公司IT运维同事和部分管理层,对系统的性能和并发要求不高,但希望界面清晰、操作流畅。
初期尝试:选型对比

最初我也想试试其他轻量级框架比如Flask或者FastAPI,但很快发现,对于一个刚入行的人来说,要自己实现用户认证、后台模板、表单处理这些通用功能,学习成本太高。
而Django正好是一站式解决方案。它自带了用户系统、数据库ORM、Admin后台、模板引擎、安全防护等等,几乎是开箱即用。虽然灵活性略逊于Flask,但在快速开发的前提下非常合适。
最后我还是选择了Django,作为我的首次实战项目。
遇到的第一个挑战:环境搭建不顺利
刚开始的时候遇到几个典型问题:

问题1:pip install django 安装失败
第一次安装时,执行pip install django报错一堆依赖冲突,后来才知道是虚拟环境没配好。
✅ 解决办法:强烈建议使用python -m venv或virtualenv创建独立虚拟环境,并激活后再安装Django。
# 创建并激活虚拟环境
python3 -m venv env
source env/bin/activate # Linux/Mac
env\Scripts\activate # Windows
然后安装稳定版本的Django(以4.2为例):
pip install "django==4.2"
📌 小提示:不要盲目追新版本,除非你确实需要某些高级特性,否则建议使用LTS(长期支持)版,避免踩兼容性坑。
问题2:运行runserver时报错找不到模块
有时候新建完项目启动服务时会遇到类似这样的错误:
ModuleNotFoundError: No module named 'django.core'
✅ 解决办法:确认是否忘记激活虚拟环境,或者Django没有正确安装。可以用 pip list 查看当前环境是否已包含Django库。
建模设计:数据库结构是关键
接下来是最核心的一部分:数据模型的设计。
根据需求,我们需要记录资产的基本信息,比如:
- 名称、类型、SN号、购买时间、负责人、当前状态等。
所以我定义了一个名为Asset的模型:
from django.db import models
from django.contrib.auth.models import User
class Asset(models.Model):
CATEGORY_CHOICES = [
('computer', '电脑'),
('server', '服务器'),
('network', '网络设备'),
('other', '其他'),
]
STATUS_CHOICES = [
('in_use', '在用'),
('idle', '闲置'),
('repair', '维修'),
('disposed', '报废'),
]
name = models.CharField('名称', max_length=100)
category = models.CharField('类别', max_length=50, choices=CATEGORY_CHOICES)
sn = models.CharField('序列号', max_length=100, unique=True)
purchase_date = models.DateField('采购日期')
owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name='负责人')
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES)
def __str__(self):
return self.name
这里需要注意几点:
- 使用
choices字段可以简化下拉框选项 - 外键关联User表实现了权限控制的基础
unique=True防止重复录入资产编号- 每个字段都加了中文verbose_name,便于Django Admin显示
在数据库方面,Django默认使用SQLite,但对于生产环境来说不太合适。我后来换成PostgreSQL,原因如下:
- 支持更复杂的查询、事务机制
- Django ORM对其优化更好
- 后续可能有大数据迁移计划
路由与接口设计:前后端交互的关键
路由和视图设计上,我采取前后端混合的方式,因为这次项目不需要复杂前端,使用Django内置的模板系统即可满足需求。
不过为了方便后期扩展REST API,我在urls.py里做了统一规划:
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.asset_list, name='asset_list'),
path('add/', views.asset_add, name='asset_add'),
path('<int:pk>/edit/', views.asset_edit, name='asset_edit'),
path('<int:pk>/delete/', views.asset_delete, name='asset_delete'),
# 新增接口用于前端AJAX调用
path('api/list/', views.AssetListView.as_view(), name='api_asset_list'),
]
同时我采用类视图方式编写接口逻辑,方便后续维护和复用:
# views.py
from django.views.generic import View
from django.http import JsonResponse
class AssetListView(View):
def get(self, request):
assets = Asset.objects.all()
data = list(assets.values('id', 'name', 'category', 'status'))
return JsonResponse(data, safe=False)

⚠️ 注意点:JSON响应要用
.values()取值并转成list,才能被Django的JsonResponse接受。
开发过程中的真实“踩坑”记录
下面分享几个让我印象深刻的坑和对应的解决经验,希望能帮你在开发过程中少走弯路。
坑1:静态文件加载不出来
开发后台页面的时候,引入CSS和JS始终加载失败,页面样式混乱。
✅ 排查步骤:
- 检查settings.py中
STATIC_URL配置是否正确 - 把静态文件放在
static目录下,并在HTML中使用{% static %}加载
{% load static %}
<link rel="stylesheet" href="{% static 'css/main.css' %}">
- 运行
collectstatic命令收集静态文件(部署时必须运行)
python manage.py collectstatic
坑2:Admin自定义太难?
Django自带的admin系统很方便,但如果直接暴露所有字段给运维同事,显得太原始。我想做个自定义页面,展示资产统计数据。
✅ 解决思路:
继承ModelAdmin,自定义页面模板,添加统计面板。
from django.contrib import admin
from .models import Asset
from django.db.models import Count
from django.utils.html import format_html
@admin.register(Asset)
class AssetAdmin(admin.ModelAdmin):
list_display = ['name', 'sn', 'category', 'status']
list_filter = ['category', 'status']
change_list_template = "admin/asset_change_list.html"
def changelist_view(self, request, extra_context=None):
response = super().changelist_view(request, extra_context=extra_context)
try:
queryset = response.context_data['cl'].queryset
except (AttributeError, KeyError):
return response
stats = {
'total': queryset.count(),
'used': queryset.filter(status='in_use').count(),
'idle': queryset.filter(status='idle').count(),
}
response.context_data['stats'] = stats
return response
然后在templates/admin/asset_change_list.html中就可以渲染对应的数据。
坑3:用户权限判断写死了?
最开始我在每个视图里都手动判断用户是否登录和是否有权限,后来代码越来越乱,而且权限判断分散在各个地方,难以维护。
✅ 解决方案:使用装饰器+中间件统一处理权限逻辑
from functools import wraps
from django.shortcuts import redirect
def login_required(view_func):
@wraps(view_func)
def wrapped_view(request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect('login')
return view_func(request, *args, **kwargs)
return wrapped_view
然后在需要的视图前加上装饰器:
@login_required
def asset_add(request):
...
这样权限判断就统一起来了。
上线部署:别忽视生产环境的细节
项目本地测试没问题,但上线时又遇到了几个新问题。
部署环境说明:
- 主机:阿里云ECS,CentOS 7
- Web服务器:Nginx + Gunicorn
- 数据库:PostgreSQL
- 域名解析:绑定到了一个二级域名 asset.internal.xxx.com
问题1:Gunicorn启动失败,日志为空
一开始照着网上教程配置gunicorn,结果启动失败,但没有任何输出。
✅ 解决方法:
- 查看gunicorn是否以daemon模式运行,需要指定--log-file参数
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000 --daemon --log-file /var/log/gunicorn.log
- 也可以先不加daemon运行看看前台输出日志
问题2:Nginx代理设置错误,导致访问路径不对
前端请求 /static/ 路径的资源,返回404。
✅ 配置示例:
server {
listen 80;
server_name asset.internal.xxx.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /static/ {
alias /path/to/static_root/;
}
}
⚠️ 特别注意:这里的/path/to/static_root/必须和settings.py中的STATIC_ROOT保持一致,也就是运行过collectstatic后的目录位置。
问题3:数据库连接超时
项目上线初期经常出现数据库连接异常。
✅ 排查结果:
原来是数据库连接池没有合理配置,每次请求都重新建立连接。后来加上了dj-database-url配合连接池插件psycopg2-binary解决了这个问题。
# settings.py
import dj_database_url
DATABASES = {
'default': dj_database_url.config(
default='postgres://user:password@localhost:5432/dbname',
conn_max_age=600
)
}
最终效果:系统稳定上线,效率提升显著
经过近三周的努力,系统终于上线运行。从最初的磕磕绊绊,到最终流畅运行,整个过程让我深刻体会到了Django在中小型项目上的优势。
- 提升了IT部门的资产管理效率,原本需要半小时的录入工作现在几分钟就能完成
- 实现了简单的权限划分,普通用户只能查看资产列表,管理员可进行编辑和删除
- 页面简洁直观,用户反馈良好
更重要的是,通过这个项目,我掌握了:
- Django项目的整体架构设计
- ORM的高级用法
- 权限控制的实现
- 接口和页面的整合
- 前端与后端协作的实践
- 生产环境部署和调试技巧
给新手的一些建议与经验总结
如果你也是刚接触Django的新手,以下是我走过弯路后的一些心得总结:
✅ 建议1:从官方文档起步,别急着抄别人的项目
很多人喜欢直接搜“Django博客系统”,结果越学越懵。建议老老实实读一遍Django官方教程,了解MTV架构、模型定义、URL映射、模板渲染这些基础概念。
✅ 建议2:善用Django Admin,它比你想象中强大
很多人觉得Admin只是后台管理工具,其实可以通过重写模板、添加自定义列、集成统计图表等方式,把它打造成强大的业务平台。
✅ 建议3:多用装饰器或中间件解耦业务逻辑
权限验证、日志记录、性能监控都可以通过中间件和装饰器统一处理,减少视图函数的臃肿。
✅ 建议4:数据库设计尽量提前考虑扩展性
虽然Django的迁移机制很友好,但在设计模型时,最好预留一些扩展字段或者通过外键关联来应对未来变化。
✅ 建议5:上线前务必压测!
即便是一个小系统,在高并发下也可能暴露性能瓶颈。可以通过Locust等工具模拟压力测试,检查慢SQL、缓存命中率等问题。
写在最后:Django依旧是你值得掌握的技术栈之一
这两年Django在国内的热度似乎不如Go语言那么火,但我始终觉得它在一个成熟的Web开发体系中有着不可替代的优势:
- 成熟稳定的生态
- 社区活跃,文档丰富
- 快速交付的能力
- 强大的ORM能力
- 合理的工程组织方式
尤其对于初创项目或企业内部落地的小系统,Django仍是首选框架之一。
如今再回头看看那个第一次写出来的资产系统,虽然简单,却是我职业生涯中一次重要的成长转折点。愿这篇文字能给你带来些许启发,也欢迎在评论区交流你的Django学习故事。
共勉之!

评论 0