从滴滴到新公司,我用 Django 快速搭了个内部工具站

霸气_导师
2026-04-03 10:36
阅读 1744

上周五晚上十点,办公室只剩下我和运维小哥。他一边啃着冷掉的黄焖鸡,一边幽幽地问我:“你那个司机接单统计页面,什么时候能上线?”我盯着屏幕里一堆未读的 Jira 通知,心里一阵发虚——这活儿本来该前端干的,但产品经理说“先做个 MVP 看看效果”,结果前后端全落我头上了。

入职这家新公司才两个月,团队还在磨合期,技术栈五花八门:老系统是 Java Spring Boot,新项目想上 Go,还有几个 Python 爬虫在默默跑着数据。而我,一个刚从滴滴出来、写了四年司机端后端的老码农,突然被拉去搞个内部管理后台——UI 要有,接口要快,还得支持导出 Excel。

思来想去,与其在 Java 里折腾 Thymeleaf 或硬上 React + Spring,不如直接用 Django 搞个全栈方案。毕竟,在滴滴那会儿,我们虽然主力是 Java 微服务,但内部工具、运营平台基本都是 Django 写的——快、稳、省心。

于是,我决定用 Django 搭建我的第一个“正经”Python 网站,并把踩过的坑和最佳实践整理出来。这篇文章不讲 Hello World,只聊真实场景下的快速交付与架构考量


为什么不是 Java?也不是爬虫?

先澄清一个误区:很多人觉得 Python = 爬虫,Django = 学生玩具。我在滴滴带过实习生,他们一听说用 Python,第一反应就是“是不是要写爬虫抓数据?”——拜托,那是 requests + BeautifulSoup 的活,跟 Web 框架半毛钱关系没有。

至于 Java,它当然强大。我在滴滴司机端的核心订单状态机、计费引擎、推送服务全是 Java 写的,稳定性扛住了双11级别的流量洪峰。但问题是:内部工具不需要高并发,需要的是开发速度

Django 的优势在于:

  • 自带 Admin 后台,5 分钟就能有个 CRUD 界面
  • ORM 抽象好,不用手写 SQL(但你知道啥时候该绕过它)
  • 中间件机制清晰,适合做权限、日志、审计等横切逻辑
  • 部署简单,gunicorn + nginx 套路成熟

更关键的是——我现在重度依赖 ChatGPT 和 Claude 辅助编码。而 Python 的语法简洁,LLM 生成的代码可读性远高于 Java 的样板代码。比如让 Claude 帮我生成一个带分页、搜索、导出的司机列表接口,它三秒就给我 Django View + Serializer + URLconf,我只需要微调字段名。


项目初始化:别再 django-admin startproject 就完了

很多教程教你 django-admin startproject mysite,然后直接 runserver。这在本地跑 demo 没问题,但一到生产环境就翻车。

我在新公司的第一版部署就被运维骂了:“你这 settings.py 里数据库密码是明文?还 commit 到 Git 了?” 当时真的想钻地缝。

正确姿势

  1. 拆分 settings 文件
    创建 settings/ 目录,包含:

    • base.py:通用配置
    • local.py:本地开发
    • production.py:线上环境
  2. 敏感信息用环境变量

    # settings/production.py
    import os
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': os.getenv('DB_NAME'),
            'USER': os.getenv('DB_USER'),
            'PASSWORD': os.getenv('DB_PASSWORD'),
            'HOST': os.getenv('DB_HOST'),
        }
    }
    
  3. 用 pydantic 或 django-environ 校验配置
    避免线上因少配一个 env 导致 500。

  4. 静态文件交给 CDN
    别指望 Django 自己 serve staticfiles 上生产。用 Whitenoise 开发方便,但正式环境务必配 nginx 或对象存储。


数据库设计:别信 ORM 能解决一切

Django ORM 确实香,.filter().select_related().prefetch_related() 写起来行云流水。但我在滴滴吃过亏——曾经一个司机画像接口,因为没注意 N+1 查询,线上慢到超时,报警响彻凌晨三点。

最佳实践

  • 外键别滥用:内部工具的数据量不大,但关系复杂。比如“司机-车辆-订单-投诉”,如果每个都外键关联,Admin 页面加载会卡死。适当冗余字段(如缓存司机姓名)反而更高效。
  • 索引必须显式声明:ORM 不会自动给你加复合索引。比如按城市+状态查询司机,记得:
    class Driver(models.Model):
        city = models.CharField(max_length=20)
        status = models.CharField(max_length=20)
        
        class Meta:
            indexes = [
                models.Index(fields=['city', 'status']),
            ]
    
  • 避免在 Model 里写业务逻辑:把核心逻辑抽到 service 层。这样单元测试好写,也方便未来迁移到其他框架(比如哪天公司又要转 Go)。

接口设计:RESTful 不是唯一答案

很多新人执着于“标准 REST”,非要搞 /drivers/{id}/orders 这种嵌套路由。但在内部工具里,实用主义 > 规范主义

我的做法:

  • 简单 CRUD:用 DRF(Django REST Framework)快速生成 API
  • 复杂操作:单独写一个 action view,比如 /api/drivers/bulk-update-status
  • 导出功能:别返回 JSON,直接返回 CSV 文件流
# views.py
def export_drivers_csv(request):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="drivers.csv"'
    writer = csv.writer(response)
    writer.writerow(['ID', 'Name', 'City', 'Status'])
    for driver in Driver.objects.all():
        writer.writerow([driver.id, driver.name, driver.city, driver.status])
    return response

测试同学看到这个功能时眼睛都亮了:“终于不用手动复制粘贴 Excel 了!” —— 这就是内部工具的价值。


关于 Windsurf:别被新玩具带偏节奏

最近团队里有人安利 Windsurf(一个新兴的 AI 编程 IDE),说能自动生成整个 Django 项目。我试了试,确实能一键创建带用户认证、Admin、API 的骨架。

但问题来了:它生成的代码不符合团队规范。比如没拆 settings,没加日志中间件,模型没加索引。更糟的是,它默认用 SQLite,而我们生产环境是 PostgreSQL。

所以我的建议是:AI 工具可以加速脚手架搭建,但架构决策不能外包给 LLM。你可以用 Windsurf 生成初稿,但必须人工 review 并重构。就像我刚入职时写的第一个 PR,被 Tech Lead 批了三条:没写 migration 注释、没加 rate limit、没处理空列表边界——这些细节,AI 可不会提醒你。


部署上线:别让运维半夜打电话

Docker 化是底线。哪怕只是个内部工具,也得做到“一次构建,到处运行”。

我的 Dockerfile 精简版:

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "mysite.wsgi"]

配合 docker-compose.yml 做本地调试:

version: '3'
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DB_HOST=db
    depends_on:
      - db
  db:
    image: postgres:14
    environment:
      POSTGRES_DB: mysite
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass

上线前务必检查:

  • 是否收集了 static files?(collectstatic)
  • 是否执行了 migrations?(别忘了 --no-input
  • 日志是否输出到 stdout?(方便 k8s 采集)

总结:Django 不是玩具,是生产力武器

写完这个内部工具,从需求到上线只用了三天。产品经理满意,测试不再抱怨数据导出麻烦,运维也没再半夜 call 我。

回头想想,Django 的真正价值不在于它多“高级”,而在于它让后端开发者能独立交付完整产品。在滴滴时,我们司机端的运营活动页、灰度开关平台、司机申诉审核系统,全是 Django 支撑的。它们不面对 C 端用户,但直接影响业务效率。

所以,如果你是个 Java 后端(像我以前那样),别瞧不起 Python Web 开发。当你需要快速验证想法、搭建内部系统、甚至写个数据可视化面板时,Django + Admin + DRF 的组合拳,可能比 Spring Boot + Vue 快一个数量级。

最后送大家一句我在新公司学到的真理:技术选型不看语言热度,看交付速度和维护成本

对了,那个司机接单统计页面,现在每天有 200+ 运营在用。而我,终于能在周五晚上准时下班了。

评论 0

最热最新
暂无评论
霸气_导师Lv.1
0
影响力
0
文章
0
粉丝