我用 Django 搞了个“区块链风”网站?入职两个月的血泪初体验

队列在排队
2026-01-15 02:50
阅读 618

大家好,我是小林,一个刚入职某中型 SaaS 公司不到俩月的后端“萌新”。名义上是正式员工,实际上还在试用期战战兢兢地活着——每天早上打开电脑第一件事就是看 GitLab 有没有被 Code Review 吐槽,下午三点准时祈祷产品经理别突然甩个需求过来。

说来惭愧,我虽然在校期间折腾过 Rust、玩过 Solidity 写智能合约(对,就是那个和区块链沾边的玩意),但进公司第一天就被老架构师一句话打回现实:“小林啊,新技术我们鼓励学,但线上系统必须稳如老狗。你先用 Django 把用户管理模块搭起来。”

于是,就有了这篇教程。不,准确地说,是一篇“血泪踩坑实录”。本文全程基于我上周五加班到九点、靠 ChatGPT 和 Claude 轮流续命才跑通的真实项目。如果你也刚入行,或者正被领导逼着用 Django 快速出活,那咱们算是一条船上的人了。


为啥是我这个“区块链民工”来写 Django 教程?

先交代背景:我本科毕业设计搞的是基于以太坊的去中心化投票系统,满脑子都是 Merkle Tree 和 Gas Fee。结果入职后发现,公司主力技术栈是 Python + Django + PostgreSQL,连 Redis 都只用来做缓存,别说区块链了——我们连 Web3 的影子都没见过。

但上周二,产品突然丢来一个需求:“我们要做一个内部工具平台,支持多租户、权限隔离,还要能快速接入新模块。” Deadline 是下周五上线 MVP。我当场瞳孔地震:这不就是典型的 CRUD 系统吗?但老板补了一句:“界面要像 Notion,性能要扛住 500 并发,下周演示给投资人看。”

行吧。既然不能上链(其实根本没必要),那就老老实实用 Django 搞个“看起来很高级”的网站吧。而且说实话,Django 的 admin 后台和 ORM 真香,比手写 SQL 省了八百条命。


从零开始:三行命令跑起你的第一个 Django 站点

别被吓到,Django 虽然“全功能”,但起步其实超快。前提是——你别像我一样手贱升级 Python 到 3.12 结果一堆包报错。

# 创建虚拟环境(强烈建议!)
python -m venv mysite_env
source mysite_env/bin/activate  # Linux/Mac
# mysite_env\Scripts\activate   # Windows

# 安装 Django(我用的是 4.2 LTS 版,稳定!)
pip install django==4.2.7

# 创建项目
django-admin startproject mysite
cd mysite
python manage.py runserver

浏览器打开 http://127.0.0.1:8000,看到那个火箭图标了吗?恭喜,你的“区块链级”网站已经上线了(手动狗头)。

🤓 小贴士:千万别在公司内网直接 runserver 对外暴露!我们运维大哥上周刚骂完一个实习生,说他把开发服务器绑到 0.0.0.0 还开了公网 IP,差点被扫爆。


数据库设计:别让字段命名毁掉你的职业生涯

我们这次要做的是一个简单的“项目看板”系统,类似 Trello,但砍掉了 90% 功能。核心模型就两个:ProjectTask

# models.py
from django.db import models
from django.contrib.auth.models import User

class Project(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

class Task(models.Model):
    STATUS_CHOICES = [
        ('todo', '待处理'),
        ('doing', '进行中'),
        ('done', '已完成'),
    ]
    title = models.CharField(max_length=200)
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='tasks')
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='todo')
    assignee = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
    due_date = models.DateField(null=True, blank=True)

这里有几个血泪教训:

  • 别用中文字段名:虽然 Django 支持 verbose_name 显示中文,但数据库列名还是英文。否则以后写 raw SQL 你会疯。
  • 外键别乱删on_delete=models.CASCADE 要慎用!我们测试环境曾因为删一个用户,连带干掉了 200 个项目,测试妹子差点拿键盘砸我。
  • 时间字段加索引:如果经常按 created_at 查询,记得加 db_index=True。不然等数据量上来,慢查询日志里全是你的名字。

视图与模板:Django 的 MTV 架构真不是吹的

Django 用的是 MTV(Model-Template-View),不是 MVC。别杠,官方就这么叫。

我一开始想直接用 FBV(Function-Based View),但老工程师看了直摇头:“现在谁还手写分页逻辑?用 CBV(Class-Based View)+ ListView,三行搞定。”

于是有了下面这段:

# views.py
from django.views.generic import ListView, CreateView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Project

class ProjectListView(LoginRequiredMixin, ListView):
    model = Project
    template_name = 'projects/list.html'
    context_object_name = 'projects'
    
    def get_queryset(self):
        return Project.objects.filter(owner=self.request.user)

配合模板:

<!-- templates/projects/list.html -->
{% extends "base.html" %}
{% block content %}
<h1>我的项目</h1>
<ul>
{% for project in projects %}
  <li>{{ project.name }} - {{ project.created_at|date:"Y-m-d" }}</li>
{% endfor %}
</ul>
{% endblock %}

是不是清爽多了?而且自带登录校验(LoginRequiredMixin),省得我手写 if not request.user.is_authenticated

💡 吐槽:我们前端同事看到模板里的 {% %} 直呼“这是什么远古语法”,我说这是 Django 的传承,他回我“传承个锤子,不如 JSX”。算了,各自安好。


区块链?不,但我们可以“假装有链”

说到关键词“区块链”——我知道你们等着呢。实话实说,这个项目跟区块链半毛钱关系没有。但为了满足标题要求(以及我那点虚荣心),我在后台悄悄加了个“操作日志”功能,记录每次任务状态变更,并生成一个 SHA256 哈希值,美其名曰“不可篡改日志”。

import hashlib
from django.db import models

class TaskLog(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    old_status = models.CharField(max_length=10)
    new_status = models.CharField(max_length=10)
    changed_by = models.ForeignKey(User, on_delete=models.CASCADE)
    timestamp = models.DateTimeField(auto_now_add=True)
    hash = models.CharField(max_length=64, unique=True)

    def save(self, *args, **kwargs):
        if not self.hash:
            data = f"{self.task.id}{self.old_status}{self.new_status}{self.changed_by.id}{self.timestamp}"
            self.hash = hashlib.sha256(data.encode()).hexdigest()
        super().save(*args, **kwargs)

这样每次状态变更都会生成唯一哈希,理论上可以链式追溯(虽然没真做链)。产品经理看了直夸“有 Web3 内味了”,我默默咽下一口老血。


性能与部署:别让 demo 变成事故

本地跑得欢,上线火葬场。这是我们团队的座右铭。

为防翻车,我做了几件事:

  1. 启用 Gunicorn + Nginx:别再用 runserver 上生产!
  2. 静态文件交给 CDN:Django 自带的 staticfiles 在高并发下会卡死。
  3. 数据库连接池:用 django-db-geventpool 或直接上 PgBouncer。
  4. 缓存关键查询:比如用户权限列表,用 Redis 缓存 5 分钟。

部署配置对比表:

组件 开发环境 生产环境
Web Server Django dev server Gunicorn + Nginx
DB SQLite PostgreSQL 14
Static Files 本地 serve AWS S3 + CloudFront
日志 控制台输出 ELK 集中收集
缓存 Redis

上线前夜,我和运维兄弟一起压测。用 Locust 模拟 500 用户并发访问项目列表页,QPS 从 12 暴涨到 180+,全靠加了 select_related('owner') 和 Redis 缓存。那一刻,我终于理解什么叫“性能是抠出来的”。


写在最后:新人如何快速融入技术栈?

入职两个月,我最大的感悟是:别炫技,先交付

我曾经以为会写智能合约就很牛,结果发现公司最需要的是能把用户注册登录流程写得又快又稳的人。Django 的“开箱即用”特性在这种场景下简直是神兵利器——Admin 后台五分钟搭好,用户认证系统不用自己造轮子,ORM 让我告别了 SQL 注入噩梦。

当然,我也在业余时间继续研究区块链。但工作归工作,爱好归爱好。就像我们 CTO 说的:“先学会用螺丝刀,再想着造火箭。”

所以,如果你也是刚入行的小白,别怕从 Django 这种“老派”框架开始。它可能不够酷,但它能让你在试用期活下去——而活下去,才有机会去折腾那些真正酷的东西。

对了,今天 HR 刚通知我,试用期考核通过了。据说是因为“项目交付及时、代码规范、没惹运维生气”。行吧,这大概就是职场生存的终极奥义了。


附:常用命令速查

# 创建 app
python manage.py startapp projects

# 生成迁移文件
python manage.py makemigrations

# 执行迁移
python manage.py migrate

# 创建超级用户(用于 admin)
python manage.py createsuperuser

# 收集静态文件(部署用)
python manage.py collectstatic --noinput

祝各位都能顺利转正,少背锅,多涨薪。代码无 bug,生活有惊喜。

评论 0

最热最新
暂无评论
队列在排队Lv.1
0
影响力
0
文章
0
粉丝