models.py
Django 入门实战:我用它搭建了人生第一个 Python 网站

作为一名后端开发者,我在加入现在这家互联网公司之前,其实对 Web 框架的理解更多停留在理论层面。真正让我深入接触并爱上 Django 的,是我入职后接到的第一个小项目——一个内部的“工单流转系统”。虽然不是特别复杂的功能,但对于刚入行的我来说,是个非常好的练手机会。
今天就来聊聊我当时是怎么一步步从零开始搭起这个 Django 项目,并在这个过程中踩了哪些坑、学到了什么经验。如果你也刚刚接触 Python Web 开发,希望这篇文章能帮你少走弯路。
背景与挑战
我们团队当时需要一个轻量级的工单管理系统,用来接收产品和技术组的简单需求,比如“请后端加个字段”,“前端帮忙优化下按钮样式”这类任务。这些请求平时是通过飞书群聊或文档记录的,容易遗漏和混乱。
老板的要求很明确:“两周内上线一个可以登记、分配、处理状态变更的界面即可,不需要太 fancy。”
听起来不难,但如果真做起来,还是有很多细节要考虑:
- 需要用户登录认证机制
- 工单的数据结构设计
- 后台接口的设计(RESTful)
- 页面交互要尽可能友好
- 生产部署方案
- 数据权限控制(谁能看到谁的工单)
这个时候我选择了 Django。一方面因为公司技术栈本身就有在用 Django,另一方面我之前对 Flask 更熟悉些,但这次想换个框架试试看。结果没想到,Django 提供的 Admin 后台、ORM、安全机制等让我效率大大提升。
技术方案选择与实现思路
整个系统的架构很简单,使用经典的前后端分离模式,后端基于 Django + DRF (Django REST framework),前端用 Vue.js 搭了个 SPA 页面,数据库是 PostgreSQL。这里重点讲 Django 相关的实现过程。
项目结构
tickets/
├── config/ # 设置相关
│ ├── settings.py
│ └── urls.py
├── tickets_api/ # 核心模块
│ ├── models.py
│ ├── views.py
│ ├── serializers.py
│ └── urls.py
├── manage.py
└── requirements.txt
这样划分主要是为了后续扩展方便,避免所有业务逻辑都堆在一个 app 中。
数据模型设计
工单系统最重要的当然是数据库设计。我的核心模型有三个:User、Ticket、TicketStatus。
from django.db import models
from django.contrib.auth.models import User
class Ticket(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
submitter = models.ForeignKey(User, on_delete=models.CASCADE, related_name='submitted_tickets')
assignee = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_tickets')
status = models.ForeignKey('TicketStatus', on_delete=models.PROTECT)

def __str__(self):
return self.title
class TicketStatus(models.Model):
name = models.CharField(max_length=50)
sequence = models.IntegerField(default=0)
class Meta:
ordering = ['sequence']
def __str__(self):
return self.name
这种设计有几个好处:
- 所有操作时间记录清晰
- 责任人和提交者分开管理
- 状态独立出来,方便未来扩展流程引擎或者审批流
不过一开始我直接用了 CharField 去存状态名称,比如 “opened”, “in_progress”, “closed”,后来发现状态变化顺序很重要,所以才抽象出 TicketStatus 这张表,支持排序和动态修改。
快速上手:搭建你的第一个 Django 项目
注意:下面的操作都是基于 Django 4.x 和 Python 3.11 的环境演示。建议你先准备好虚拟环境。
安装依赖 & 初始化项目
pip install django djangorestframework python-dotenv
django-admin startproject config .
创建 App
python manage.py startapp tickets_api
然后别忘了在 settings.py 中添加 app 到 INSTALLED_APPS。
编写 API 接口
使用 DRF 来暴露 RESTful API 非常方便。首先写个 Serializer:
# serializers.py
from rest_framework import serializers
from .models import Ticket, TicketStatus
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username']
class TicketSerializer(serializers.ModelSerializer):
submitter = UserSerializer(read_only=True)
assignee = UserSerializer(read_only=True, allow_null=True)
status = serializers.StringRelatedField()
class Meta:
model = Ticket
fields = '__all__'
接着写 ViewSet:
# views.py
from rest_framework import viewsets
from .models import Ticket
from .serializers import TicketSerializer
class TicketViewSet(viewsets.ModelViewSet):
queryset = Ticket.objects.all().order_by('-created_at')
serializer_class = TicketSerializer
注册路由:
# config/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from tickets_api.views import TicketViewSet
router = DefaultRouter()
router.register(r'tickets', TicketViewSet)
urlpatterns = [
path('', include(router.urls)),
]
这样 /tickets/ 接口就已经 ready,GET/POST/PUT/DELETE 功能一应俱全,而且自带分页和过滤功能,是不是超级快?
实际开发中遇到的问题和解决方法
用户权限问题
刚开始没做权限校验,所有人都可以删工单。后来紧急加上了权限类:
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
class TicketViewSet(...):
authentication_classes = [SessionAuthentication, TokenAuthentication]
permission_classes = [IsAuthenticated]
再配合 Django 的 Group 和 Permission 系统来做细粒度控制。比如管理员可以删除所有工单,普通用户只能看自己的。
数据库迁移失误
有一次线上执行了一个带有数据转换的 migration,在生成新的字段时忘了加 null=True,导致旧数据迁移时报错。后来改回:
new_field = models.CharField(max_length=100, null=True, blank=True)
再通过数据迁移脚本补充默认值。
Tip:生产环境每次迁移前一定要本地先跑一遍,最好结合 django-extensions 的 graphmigrations 看清楚依赖关系。
性能瓶颈
最初上线后发现访问 /tickets 接口偶尔超时。分析发现是查询没有 select_related 导致 N+1 查询问题。
修复办法很简单:
queryset = Ticket.objects.select_related('submitter', 'assignee', 'status').all()
再加上缓存机制,把高频读取的列表缓存在 Redis 里,命中率大概 70%左右,QPS 一下就降下来了。
部署上线与运维经验
使用 Gunicorn + Nginx 部署
后端服务用 Gunicorn 跑起来:
gunicorn -w 4 config.wsgi:application --bind 0.0.0.0:8000
Nginx 转发配置示例:
server {
listen 80;
server_name yourdomain.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/files/;
}
}
使用 Whitenoise 处理静态文件
如果你不想用 CDN,可以用 Whitenoise:
pip install whitenoise
然后在 settings.py 加上:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
...
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
上线后监控日志
推荐几个好用的工具:
- Sentry:捕获异常错误
- Prometheus + Grafana:监控请求延迟、QPS、HTTP 状态码
- 自建 Log 日志收集系统(ELK 或 Loki)
最终效果与收益
最终这个系统上线后反响还不错,产品经理说比之前手动管理高效多了。一些成果数字如下:
- 平均响应时间从最初的 500ms 优化到 80ms
- 支持了权限隔离、多角色管理
- 后续接入了通知系统,可以在钉钉收到提醒
- 成为其他团队复用的“样板工程”
更重要的是,我通过这个项目彻底掌握了 Django 的工作流、权限体系、REST API 设计和部署方式,也为我之后参与更大的项目打下了坚实基础。
经验总结与建议
写给新手的几点建议:
- 不要追求一开始就写最完美的模型:先把功能跑通,再逐步优化。
- 合理使用 ORM,减少 raw SQL 的书写:除非必须,否则尽量用 filter、annotate 等封装好的方法。
- 提前考虑权限设计:很多项目初期不考虑权限,后面补会很痛苦。
- 重视测试和自动化:即使是一个小系统,也要写基本的单元测试,推荐 pytest。
- 学会查官方文档:Django 文档质量非常高,值得反复阅读。
Django 适合做什么?
Django 并不是万金油,它的定位更适合中型后台管理系统、CMS、API 服务等场景。对于高性能、高并发的服务,更建议结合 Go 或 Node.js 做微服务架构。
结语
这是我第一次真正意义上完整交付一个网站项目。虽然看起来只是一个简单的工单系统,但在过程中学到的东西远比预期的多得多。Django 的生态成熟、社区活跃、上手门槛适中,非常适合作为新手的第一个 Web 框架。
如果你正在学习 Python Web 开发,不妨动手试试用 Django 写个小项目,体验下什么叫“开箱即用”的开发速度。哪怕只是为了做个待办事项清单也好,实践才是成长最快的路径。
Happy coding!

评论 0