从零跑通Django:一个远程开发者的孤独建站之旅
上周五晚上十一点,我正窝在上海老小区的出租屋里,窗外是外滩方向隐约的霓虹,屋里只有机械键盘的咔嗒声和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