从零开始的 Django 实战:一个 Python 网站的成长日记
引言:第一次用 Django 搭网站,心里其实有点慌

说实话,虽然我之前写过不少 Python 脚本,也了解一些 Web 开发的基本概念,但真要动手搭一个完整的网站时,心里还是有些没底。当时我在一家初创公司负责一个小型客户管理系统的开发任务,团队决定采用 Django,因为“它成熟、开发快、社区活跃”,而且公司技术负责人以前做过 Django 项目。
作为一个刚上手不久的新手开发者,面对“搭建你的第一个 Python 网站”这样的任务,压力真的不小。整个过程充满了踩坑和反思,但也让我对 Django 的架构设计和工程实践有了深刻的理解。
这篇文章,我会以第一人称的方式带你走进那次实战开发的真实经历,分享我是如何一步步完成项目的,中间踩了哪些坑,又是怎么爬出来的。希望你能从中学到东西,也能感受到我们做开发时那种既紧张又兴奋的状态。
问题描述:需求简单?事情哪有那么容易

这个项目的目标是一个内部使用的客户关系管理系统(CRM),核心功能包括:
- 客户信息增删改查
- 客户跟进记录管理
- 用户登录系统(基于邮箱)
- 权限控制(普通用户只能看自己的客户,管理员可以管理所有)
看起来需求并不复杂,但真正落地的时候,才发现很多细节远没有想象中简单。
比如:
- 怎么设计数据库模型才能高效查询客户和他们的跟进记录?
- 用户权限要怎么做,是每个页面都加判断吗?有没有更优雅的方式?
- 登录流程需要考虑安全性和易用性,Django 自带的认证机制怎么用?
- 后台管理界面想快速出原型,要不要自己写模板,还是直接使用 Django Admin?
还有更现实的问题——时间只有三周,前端部分同事只负责样式美化,我得一手包办前后端逻辑。
这些问题叠加起来,让我有点不知所措。不过好在 Django 这个框架本身就很适合快速开发,给了我很大的信心。
解决方案:Django 是一把好刀,关键是怎么用

技术选型思路
我最终采用的技术方案如下:
- 后端:Django + DRF(Django REST Framework)提供数据接口支持前端
- 前端:Bootstrap + jQuery 快速搭建响应式界面,后续可能接入 Vue.js
- 数据库:PostgreSQL(公司统一要求用 PG,不考虑 SQLite)
- 部署环境:Nginx + Gunicorn + Supervisor
- 用户认证:自定义 User 模型(基于 Email 而非用户名)
架构设计初步
为了快速上线 MVP,我把整个项目分为两个阶段:
- 后台管理模块:先用 Django Admin 实现客户与跟进记录的管理,方便测试和初期使用。
- 前端展示模块:用 Django Template 实现基础界面,后期准备通过 DRF 提供 JSON 接口。
这样可以在最短时间内跑通业务流程,不至于陷入一开始就写接口、写页面的困境。
代码实践:从创建项目开始

创建虚拟环境和 Django 项目
# 建议使用 Python 3.9+
python -m venv env
source env/bin/activate
pip install django==4.2
django-admin startproject mycrm .
配置数据库连接(settings.py)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mycrm',
'USER': 'admin',
'PASSWORD': 'secret',
'HOST': 'localhost',
'PORT': '5432',
}
}
创建 App
python manage.py startapp customers
python manage.py startapp followups
别忘了把 app 加入 INSTALLED_APPS
自定义用户模型
因为默认的用户模型是用 username 登录的,而我们想让用户用 email 登录,所以必须自定义用户模型。
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
然后在 settings.py 设置:
AUTH_USER_MODEL = 'accounts.User'
数据库模型设计(部分示例)
客户模型(customers/models.py)
from django.db import models
from accounts.models import User
class Customer(models.Model):
name = models.CharField(max_length=100)
phone = models.CharField(max_length=20, blank=True)
email = models.EmailField(blank=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
跟进记录模型(followups/models.py)
from django.db import models
from customers.models import Customer
class Followup(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
content = models.TextField()
next_action = models.TextField(blank=True)
scheduled_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Followup for {self.customer}"
后台注册(customers/admin.py)
from django.contrib import admin
from .models import Customer
@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
list_display = ('name', 'phone', 'email', 'owner', 'created_at')
运行迁移命令:
python manage.py makemigrations
python manage.py migrate
此时数据库已经建好了表结构,管理员也可以登陆后台添加数据了。
踩坑经验:那些我以为会很简单的部分
坑一:用户模型换不了
一开始我没意识到用户模型必须尽早定义,结果在项目中期突然发现不能修改现有用户的字段。这时候再改模型就会造成混乱。教训就是:用户模型必须一开始就想清楚,并且不要中途更换或大改字段。
坑二:权限处理方式错了
最初我只是在视图函数里写了很多类似 if request.user.is_superuser: ... 的判断,但后来发现这样不仅难维护,还容易出错。
正确的做法应该是:
- 使用 Django 内建的装饰器:
from django.contrib.auth.decorators import login_required, user_passes_test
@login_required
def some_view(request):
...
def is_admin(user):
return user.is_superuser
@user_passes_test(is_admin)
def admin_only_view(request):
...
还可以用 Mixin 类来做通用处理,比如:
from django.utils.decorators import method_decorator
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
@method_decorator(login_required, name='dispatch')
class ProtectedView(LoginRequiredMixin, View):
...
坑三:Django Admin 本地化设置搞错了
我们项目是国内客户使用,所以日期格式要用中文。结果我配置了半天才发现原来要在 settings.py 中加上这些:
LANGUAGE_CODE = 'zh-hans'
USE_I18N = True
USE_L10N = True
不然 Admin 页面里的日期还是英文格式。
坑四:静态文件路径配置翻车
本地开发没问题,部署到服务器后静态文件全 404。后来才发现 Nginx 没正确指向 Django 收集后的 static 文件目录。解决方案是:
python manage.py collectstatic --noinput
然后在 Nginx 配置中加入:
location /static/ {
alias /path/to/static_root/;
}
效果总结:快速上线,用户反馈不错
用了大约两周时间完成了 MVP,部署到了公司的测试环境。前端同学配合做了几个页面,用户可以查看客户列表、添加跟进记录,还能看到自己的待办事项。
用户反馈整体不错,尤其是他们觉得“后台操作流畅,响应速度快”。这得益于 Django 对 ORM 查询的优化能力,以及我们在 DB 层面做的索引策略。
虽然不是什么高并发的应用,但在单台服务器上轻松应付每天几千次请求也没有任何问题。
经验分享:给新手的一些建议
1. 学会合理利用 Django Admin
很多时候,你会发现自己其实不需要从头开始写后台系统。Django Admin 功能非常强大,稍微定制一下就可以满足大多数管理需求。节省的时间完全可以投入到更有价值的开发中去。
2. ORM 不是万能的,也要学会写 SQL
Django ORM 很方便,但它也不是万能的。尤其是在做一些关联查询或者聚合统计时,有时候写原生 SQL 更清晰,效率更高。要学会结合 ORM 和 SQL 优势互补。
3. 权限控制要有层次感,不要随便用 if 判断
权限逻辑应该尽可能抽象封装,可以用 middleware、decorator、mixins 等方式统一处理,避免在多个地方复制粘贴一堆判断语句。
4. 多看看官方文档和源码
Django 的文档是我见过最好的开源项目文档之一。很多你遇到的问题都能在文档里找到答案。建议多读几遍官方教程,特别是《Writing your first Django app》系列,对初学者帮助很大。
5. 学会部署才是真正的“上线”
很多人学完 Django 只会在本地 runserver,但实际上部署才是真正考验一个开发者能力的地方。Gunicorn、uWSGI、Supervisor、Nginx 这些工具都要熟悉,知道它们之间的分工和协作方式。
写在最后:框架只是工具,解决问题才是目的
回过头来看,这次实战虽然过程挺煎熬,但收获真的太大了。从最初的焦虑到逐渐上手,再到最后顺利交付,每一步都像是打怪升级。
Django 并不是一个多么复杂的框架,它的设计理念也很务实:“The web framework for perfectionists with deadlines.”(面向追求完美且时间紧迫的开发者的 Web 框架)。
对于刚入门的同学来说,只要肯动手、勤思考,很快就能做出一个像样的网站。而当你真正开始用 Django 做项目时,你会体会到它带给你的不仅仅是便利,更是一种工程上的“安全感”。
希望这篇来自实战经验的文章,能帮你少走点弯路,在学习 Django 的道路上越走越稳。

评论 0