models.py

代码轻食主义
2025-06-17 10:40
阅读 540

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

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)


![API接口文档-1](https://code-guide.oss.shanghai.autogptai.club/common/file/download?name=date2025061710/02ee44e3-c33e-44af-a917-3b42f1753479.jpg)


    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 设计和部署方式,也为我之后参与更大的项目打下了坚实基础。


经验总结与建议

写给新手的几点建议:

  1. 不要追求一开始就写最完美的模型:先把功能跑通,再逐步优化。
  2. 合理使用 ORM,减少 raw SQL 的书写:除非必须,否则尽量用 filter、annotate 等封装好的方法。
  3. 提前考虑权限设计:很多项目初期不考虑权限,后面补会很痛苦。
  4. 重视测试和自动化:即使是一个小系统,也要写基本的单元测试,推荐 pytest。
  5. 学会查官方文档:Django 文档质量非常高,值得反复阅读。

Django 适合做什么?

Django 并不是万金油,它的定位更适合中型后台管理系统、CMS、API 服务等场景。对于高性能、高并发的服务,更建议结合 Go 或 Node.js 做微服务架构。

结语

这是我第一次真正意义上完整交付一个网站项目。虽然看起来只是一个简单的工单系统,但在过程中学到的东西远比预期的多得多。Django 的生态成熟、社区活跃、上手门槛适中,非常适合作为新手的第一个 Web 框架。

如果你正在学习 Python Web 开发,不妨动手试试用 Django 写个小项目,体验下什么叫“开箱即用”的开发速度。哪怕只是为了做个待办事项清单也好,实践才是成长最快的路径。

Happy coding!

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝