从零跑通Django:一个远程开发者的孤独建站之旅

Docker搬运工
2026-01-23 22:43
阅读 1647

上周五晚上十一点,我正窝在上海老小区的出租屋里,窗外是外滩方向隐约的霓虹,屋里只有机械键盘的咔嗒声和Vim的:wq回响。突然微信弹出一条消息——“兄弟,你不是会Python吗?能不能帮我搭个内部管理后台?下周一就要用。”发信人是我前同事,现在在一家搞区块链资产追踪的小创业公司。

我盯着屏幕愣了三秒,心想:这不就是典型的“需求明天上线,代码今天才写”吗?但转念一想,反正最近远程工作节奏松散,接点小活既能练手又能赚点外快,何乐不为?于是咬牙回了个“OK”,然后默默打开了终端。

说实话,这几年我主要用Go写微服务,Django已经快三年没碰了。但架不住它“开箱即用”的诱惑——毕竟,谁不想在30分钟内跑起一个带Admin后台的网站呢?尤其对我这种独狼开发者来说,时间就是生命,能省一行配置就省一行。


为什么又捡起Django?

很多人说Django“重”,不适合现代微服务架构。这话没错,但要看场景。如果你要快速验证一个MVP(最小可行产品),或者像我这次一样,临时搭个内部工具,Django简直是救星。相比之下,用Go从零开始写CRUD、用户认证、Admin界面?那得累死。虽然我日常主力是Go(尤其是Gin或Echo框架),但面对“下周一就要用”的需求,效率优先。

而且,最近面试时也常被问到:“你用过哪些Web框架?Django和Flask有什么区别?”——这大概就是所谓的面试题挑战吧。光背八股文不如动手撸一遍,于是我决定借这个机会,彻底走一遍Django新手流程,顺便记录下来,给同样在远程办公、偶尔需要快速建站的同行们参考。


初始化:别让环境搞崩你的心态

第一步永远是环境。我习惯用pyenv + virtualenv隔离项目,避免污染全局。在终端里敲:

mkdir mysite && cd mysite
python -m venv venv
source venv/bin/activate
pip install django

💡 小贴士:别用系统自带的Python!我曾经因为Mac默认的Python2.7折腾了整整一晚,最后差点把电脑扔出窗外。

接着生成项目骨架:

django-admin startproject mysite .

注意那个.,很多人漏掉,结果项目嵌套两层目录,后期路径引用各种报错。我当年就栽过这个坑,现在看到.py文件找不到模块就条件反射检查路径。

启动试试:

python manage.py runserver

浏览器打开 http://127.0.0.1:8000,熟悉的火箭图标出现——成了!那一刻,孤独的出租屋里仿佛有了点人气。


设计模型:别急着写API,先想清楚数据结构

这次的需求很简单:一个资产登记表,记录区块链地址、所属项目、备注等。作为关注架构设计的人,我坚持先画ER图再写代码。哪怕只是三张表,也得考虑未来扩展性。

比如,BlockchainAddress 模型:

# models.py
from django.db import models

class BlockchainProject(models.Model):
    name = models.CharField(max_length=100, unique=True)
    description = models.TextField(blank=True)

    def __str__(self):
        return self.name

class BlockchainAddress(models.Model):
    address = models.CharField(max_length=64, unique=True)  # 以太坊地址长度
    project = models.ForeignKey(BlockchainProject, on_delete=models.CASCADE)
    note = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.project.name} - {self.address[:8]}..."

这里有几个关键点:

  • unique=True 防止重复录入,尤其区块链地址不能重复。
  • on_delete=models.CASCADE 表示项目删除时,关联地址也删掉——业务上合理。
  • __str__ 方法一定要写!不然Django Admin里全是 BlockchainAddress object (1),看得人眼花。

然后执行迁移:

python manage.py makemigrations
python manage.py migrate

⚠️ 踩坑预警:如果你改了字段类型(比如从CharField改成TextField),Django可能无法自动推断,需要手动编辑迁移文件。我曾因一个null=True漏写,导致线上数据库锁表十分钟,运维直接打来电话骂街。


Admin后台:Django的隐藏王牌

接下来注册模型到Admin:

# admin.py
from django.contrib import admin
from .models import BlockchainProject, BlockchainAddress

@admin.register(BlockchainProject)
class ProjectAdmin(admin.ModelAdmin):
    list_display = ('name', 'description')

@admin.register(BlockchainAddress)
class AddressAdmin(admin.ModelAdmin):
    list_display = ('address', 'project', 'note', 'created_at')
    list_filter = ('project', 'created_at')
    search_fields = ('address', 'note')

创建超级用户:

python manage.py createsuperuser

输入用户名密码,登录 /admin,奇迹发生了——一个功能完整的后台管理系统,支持搜索、筛选、增删改查,连分页都给你做好了。这要是用Go手写,至少两天工作量。

我靠在椅子上,喝了口凉透的咖啡,心想:这就是Django的魅力啊。它不炫技,但稳如老狗。


写个简单API:给前端留个接口

虽然这次是内部工具,但万一以后要接前端呢?我顺手加了个REST API。虽然Django REST Framework(DRF)更专业,但为了轻量,我直接用原生View:

# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
from .models import BlockchainAddress

@csrf_exempt
def address_list(request):
    if request.method == 'GET':
        addresses = BlockchainAddress.objects.all().values(
            'address', 'project__name', 'note', 'created_at'
        )
        return JsonResponse(list(addresses), safe=False)
    
    elif request.method == 'POST':
        data = json.loads(request.body)
        project, _ = BlockchainProject.objects.get_or_create(name=data['project'])
        addr = BlockchainAddress.objects.create(
            address=data['address'],
            project=project,
            note=data.get('note', '')
        )
        return JsonResponse({'id': addr.id}, status=201)

别忘了配路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('api/addresses/', views.address_list, name='address-list'),
]

测试一下:

curl -X POST http://127.0.0.1:8000/api/addresses/ \
  -H "Content-Type: application/json" \
  -d '{"address":"0x123...","project":"ETH Tracker"}'

返回{"id": 1},搞定!虽然简陋,但够用。真要上生产,我会换成DRF加JWT认证,但MVP阶段,够快就行。


生产部署:别让DEBUG=True上线!

很多新手教程到这就结束了,但作为经历过线上事故的老兵,我必须强调部署细节。

首先,绝对不要用runserver跑生产!它单线程、无缓存、性能差,只适合开发。正确做法是用Gunicorn + Nginx。

安装Gunicorn:

pip install gunicorn

启动命令:

gunicorn --bind 0.0.0.0:8000 mysite.wsgi

然后配Nginx反向代理,处理静态文件和HTTPS。这里有个关键点:Django的静态文件要用collectstatic收集:

python manage.py collectstatic

否则CSS/JS全404,页面丑得像90年代网页。

另外,记得关掉DEBUG

# settings.py
DEBUG = False
ALLOWED_HOSTS = ['your-domain.com', 'localhost']

否则一旦出错,Django会把整个环境变量和代码栈打印出来——包括数据库密码!我见过有团队因此泄露AWS密钥,血泪教训。


Django vs Go:工具选型的思考

写完这个小项目,我不禁对比起日常用的Go。如果用Go(比如Gin)实现同样功能,代码量其实差不多,但需要自己处理:

  • 数据库ORM(GORM虽好,但配置繁琐)
  • 用户认证(得集成JWT或OAuth)
  • Admin界面(基本得从零造轮子)

而Django把这些都打包了,牺牲了一点“灵活性”,换来了“速度”。所以我的结论是:

场景 推荐技术
快速MVP、内部工具 Django
高并发微服务、API网关 Go
区块链节点交互、高性能计算 Go + Rust

有趣的是,现在很多区块链项目后端反而用Go更多——因为需要高并发处理交易,而Django的同步模型在这种场景下就成了瓶颈。不过,管理后台用Django,核心引擎用Go,混合架构也是常见选择。


最后:孤独开发者的自白

凌晨两点,我提交了代码,发给前同事。他回了个“牛逼!”,然后没了下文。这就是远程工作的常态——没有掌声,没有团建,只有Git提交记录和银行到账短信。

但说实话,我享受这种孤独。不用开会,不用写周报,Vim里敲代码,终端里看日志,一切尽在掌控。Django这样的框架,就像一个沉默的伙伴,不吵不闹,却总在你需要的时候递上工具。

如果你也在远程办公,偶尔接到“紧急需求”,不妨试试Django。它可能不够酷,不够新,但在某些时刻,它能让你在deadline前睡个好觉。

对了,下周我打算用Go写个区块链地址监控服务,和这个Django后台对接。到时候再分享——希望那时候,我还没被产品经理的需求逼疯。

(完)

评论 0

最热最新
暂无评论
Docker搬运工Lv.1
0
影响力
0
文章
0
粉丝