Django初体验:一个成都小厂后端的Python建站实战手记

敏锐之彩虹
2025-12-21 09:47
阅读 3773

上周五晚上十点,办公室只剩下我和隔壁组那个总爱穿拖鞋的运维小哥。我盯着屏幕上一行报错信息发呆:“TemplateDoesNotExist at /”,心里默默问候了Django祖宗十八代——这都第几次了?明明照着文档一步步来的啊!

这事得从头说起。我是成都一家十几人小公司的后端开发,独立负责一条电商业务线。平时主要用Go写微服务,但最近产品经理突然提了个需求:要做个内部运营后台,用来管理用户标签和营销活动。工期两周,下周就要给老板演示。

“用Go写个Web界面?那不得累死?”我心里嘀咕。虽然我们主系统都是Go + Gin,但搞个完整的后台管理界面,光是模板渲染、表单处理、用户认证这些轮子就得造半天。更别说我还得兼顾线上系统的稳定性——去年双11期间那个Redis缓存穿透事故还历历在目,当时真的想砸电脑。

思来想去,决定试试Django。为啥?因为听说它“自带干粮”,开箱即用。而且最近刷求职网站发现,好多JD都写着“熟悉Django优先”,面试题里也经常出现Django相关的问题。作为一个有上进心(且想跳槽)的小厂程序员,这不正好是个学习机会?

为什么不是Flask或者继续用Go?

说实话,一开始我也纠结过。毕竟Go是我吃饭的家伙,而且Gin框架轻量又快。但仔细一想,在这种需要快速出原型的场景下,Go的“显式优于隐式”反而成了负担。

框架 开发速度 学习曲线 内置功能 适合场景
Django ⚡⚡⚡⚡⚡ 中等 超全(ORM、Admin、Auth等) 快速原型、全栈应用
Flask ⚡⚡⚡ 低 基础,靠扩展 微服务、API接口
Go+Gin ⚡⚡ 高 几乎没有 高性能后端服务

你看,我要的是一个带用户登录、数据展示、表单提交的完整Web应用,而不是单纯的API服务。Django的Admin后台简直就是为这种需求量身定制的——自动生成CRUD界面,连权限控制都有。

再说Flask,虽然简单灵活,但要实现同样的功能,我得自己集成SQLAlchemy、Flask-Login、WTForms等等,配置起来比写业务逻辑还费时间。在这个deadline压顶的时候,显然不是最优选择。

至于Go... 咱也不是不能写,但用echo或gin配合html/template的话,每个页面都要手动处理模板变量、CSRF防护、session管理。两天时间可能就耗在这些基础功能上了,老板怕是要把我祭天。

从零开始:三十分钟搭个能跑的网站

废话不多说,直接开干。首先确保你装了Python 3.8+(我们生产环境用的是3.9),然后:

# 创建虚拟环境(别偷懒,这是好习惯)
python -m venv django-env
source django-env/bin/activate  # Linux/Mac
# django-env\Scripts\activate   # Windows

# 安装Django
pip install django

# 创建项目
django-admin startproject ops_backend
cd ops_backend

# 创建应用(Django里叫app)
python manage.py startapp marketing

到这里,一个最基本的Django项目结构就出来了。说实话,第一次看到这么多文件夹和配置文件时我有点懵——这比Go的一个main.go复杂多了。但慢慢就发现,这种“约定优于配置”的设计其实很贴心。

关键配置都在settings.py里,比如数据库默认用SQLite(开发够用),静态文件路径、时区设置等等。我们小公司暂时没那么多讲究,先用默认配置跑起来再说。

# settings.py 关键配置示例
INSTALLED_APPS = [
    'django.contrib.admin',      # 后台管理
    'django.contrib.auth',       # 用户认证
    'django.contrib.contenttypes',
    'django.contrib.sessions',   # session支持
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'marketing',                 # 我们自己的app
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

LANGUAGE_CODE = 'zh-hans'  # 中文支持
TIME_ZONE = 'Asia/Shanghai'

接下来定义数据模型。我们的需求很简单:用户标签管理和营销活动配置。

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

class UserTag(models.Model):
    name = models.CharField('标签名称', max_length=50, unique=True)
    description = models.TextField('描述', blank=True)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    
    class Meta:
        verbose_name = '用户标签'
        verbose_name_plural = '用户标签'

class MarketingCampaign(models.Model):
    title = models.CharField('活动标题', max_length=100)
    target_tags = models.ManyToManyField(UserTag, verbose_name='目标标签')
    start_time = models.DateTimeField('开始时间')
    end_time = models.DateTimeField('结束时间')
    is_active = models.BooleanField('是否启用', default=True)
    
    class Meta:
        verbose_name = '营销活动'
        verbose_name_plural = '营销活动'

写完模型,执行数据库迁移:

python manage.py makemigrations
python manage.py migrate

这时候神奇的事情发生了——Django不仅创建了数据库表,还自动给我生成了超级用户管理界面!运行开发服务器:

python manage.py createsuperuser  # 创建管理员账号
python manage.py runserver

访问 http://127.0.0.1:8000/admin,输入刚才创建的账号密码,哇塞!所有模型的增删改查界面都自动生成了,连中文显示都完美支持。这效率,比我用Go手撸三天还快。

踩坑实录:那些让我想砸键盘的时刻

当然,事情不可能一帆风顺。第一个大坑就是静态文件。本地开发时一切正常,但当我尝试部署到测试环境时,CSS和JS全部404。

原来Django在DEBUG=False时不会自动提供静态文件服务,需要单独配置。我们小公司没专门的运维,只能自己搞定Nginx配置:

# nginx.conf 片段
location /static/ {
    alias /path/to/your/project/staticfiles/;
}

同时在settings.py里加上:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

然后执行 python manage.py collectstatic 收集所有静态文件。这个过程折腾了我整整一个下午,主要是对Django的静态文件机制理解不够深入。

第二个坑是时区问题。数据库里存的时间总是比本地时间少8小时。后来才发现Django默认使用UTC时区,而我们在settings.py里只改了TIME_ZONE,忘了告诉数据库也用本地时区。解决方案是在数据库连接配置里加上:

DATABASES = {
    'default': {
        # ...其他配置
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
            'charset': 'utf8mb4',
        },
        'TIME_ZONE': 'Asia/Shanghai',  # 显式指定
    }
}

还有一次,我在写表单验证时,因为没理解Django的CSRF机制,POST请求一直返回403。后来才知道要在模板里加上 {% csrf_token %},或者在view函数上加 @csrf_exempt 装饰器(不推荐)。这些细节看似简单,但对新手来说真的很劝退。

和Go生态的对比思考

作为一个日常写Go的开发者,用Django的过程中一直在做对比。最明显的感受是:Go追求显式和可控,Django追求约定和便利。

比如数据库操作:

  • Go中你需要自己写SQL或者用GORM这样的ORM,每一步都很明确
  • Django的ORM则高度抽象,.filter().exclude().order_by() 链式调用很爽,但有时候生成的SQL不够优化

再比如错误处理:

  • Go强制你处理每个error,虽然啰嗦但不容易遗漏
  • Django遇到异常直接抛500页面,开发时方便,但生产环境需要额外配置日志监控

不过话说回来,这两种哲学没有绝对的优劣。就像我们公司的技术栈:核心交易系统用Go保证高性能和稳定性,内部工具用Django快速迭代。综合来看,选择合适的工具比盲目追求技术先进性更重要。

这也让我想起最近面试时被问到的一个问题:“你们为什么在某些场景选择Python而不是Go?” 现在我可以自信地回答:开发效率和团队能力匹配度才是关键考量。不是所有场景都需要高并发,有时候快速交付比极致性能更有价值。

给想学Django的求职者的建议

如果你正在准备求职,特别是想进一些用Python的技术团队,Django确实是必学技能。但别只是照着教程敲代码,要深入理解它的设计思想:

  1. MTV架构模式:Model-Template-View,对应MVC中的Model-View-Controller
  2. 中间件机制:类似Go的middleware,但更强大,可以处理请求/响应的各个阶段
  3. 信号系统:解耦组件间的通知机制,比硬编码回调优雅得多

最重要的是,动手做一个完整的项目。哪怕只是简单的博客系统,也要走完从需求分析、数据库设计、API开发到部署上线的全流程。我在成都这边参加技术meetup时,很多面试官都说:“看一个人会不会Django,不用问概念,直接让他现场改个bug就知道了。”

顺便吐槽一句,我们公司最近招人,看到简历写“精通Django”的候选人,一问连QuerySet的惰性求值都不清楚,真是让人哭笑不得。技术这东西,真的要沉下心来学。

最后的碎碎念

现在这个运营后台已经上线一周了,产品经理居然没提新需求(奇迹!),老板还夸界面专业。虽然我知道背后是Django Admin的功劳,但不妨碍我小小得意一下。

在成都这座生活节奏舒服的城市,能用合适的技术快速解决问题,下班还能去太古里喝杯咖啡,感觉人生达到了巅峰。当然,如果哪天想挑战更高薪的岗位,这些积累的经验也会成为跳槽的底气。

所以啊,别管外面吹什么Go多么牛、Rust多么快,能解决实际问题的技术就是好技术。Django或许不是最性感的框架,但在特定场景下,它真的香。

对了,如果你也在小厂挣扎求生,或者正准备学习Django,欢迎在评论区交流。说不定下次meetup我们能在IFS楼下偶遇,一起吐槽产品经理呢!

(完)


后记:写这篇文章的时候,我又收到了产品经理的新消息:“那个后台能不能加个数据导出Excel的功能?” 唉,打工人的一天,从Django开始,到Django结束。不过这次我有经验了,pip install django-import-export,十分钟搞定,稳得很!

评论 0

最热最新
暂无评论
敏锐之彩虹Lv.1
0
影响力
0
文章
0
粉丝