Django入门教程:搭建你的第一个Python网站

限流小保安
2025-12-13 02:03
阅读 251

上周五晚上十点半,我瘫在工位上盯着屏幕上一堆 500 Internal Server Error,内心已经把产品经理祖宗十八代问候了个遍。事情是这样的:我们小厂最近接了个政府外包项目,要求两周内上线一个简单的数据展示平台。前端兄弟甩锅说后端接口没给,测试妹子疯狂@我问什么时候能测,运维大哥直接在群里艾特:“再不上线就别回家了。”

更要命的是,这活儿原本是另一个同事负责的,结果他周一提了离职(没错,又是金三银四跑路潮),领导二话不说把需求塞给我:“你不是会Python吗?Django搞一下呗。” 我心里一万个草泥马奔腾而过——我平时主要用Go写微服务啊!但看着工资条和北京房租,还是默默打开了PyCharm。

说起来有点惭愧,虽然在GitHub上Star了一堆Django项目,但真正动手写还是头一回。今天这篇博客,就是记录我这个“Go转Django”菜鸟如何在deadline前把网站跑起来的血泪史。顺便也回答下最近面试被问爆的面试题:“Django和Flask有什么区别?”——现在我可以拍着胸脯说:都TM是坑,但Django的坑有官方填土包!

为什么选Django?不都是Python Web框架吗?

先说背景:我们公司后端技术栈主要是Go + Gin,为啥这次不用熟悉的工具?原因很现实:

  1. 时间紧:Django自带Admin、ORM、用户认证,能快速搭出可演示的原型
  2. 需求简单:就是CRUD+数据展示,不需要高并发(政府项目嘛,流量能有多大)
  3. 团队技能:实习生会Python,后期维护有人接手

📌 面试题延伸:面试官问Django vs Flask,千万别只说“Django大而全,Flask轻量”。要结合场景!比如我说:“如果要做内部管理系统,Django省50%开发时间;如果是API网关或中间件,Flask更灵活。” 这才是加分项。

环境搭建:别让第一步就劝退你

先吐槽下Python环境管理——比Go复杂多了!Go只要装个二进制文件就行,Python还得搞虚拟环境。我用的是venv(别跟我提conda,公司服务器没权限装):

# 创建项目目录
mkdir gov-data-platform && cd gov-data-platform

# 创建虚拟环境(Python 3.8+)
python3 -m venv .venv

# 激活环境(Mac/Linux)
source .venv/bin/activate
# Windows用:.venv\Scripts\activate

# 安装Django(指定版本避免踩新坑)
pip install Django==4.2.7

💡 生产经验:一定要固定版本!去年双11期间,有个同事没锁Django版本,半夜线上报FieldDoesNotExist,原因是Django 4.2改了模型字段校验逻辑... 自此我们所有requirements.txt都带精确版本号。

创建第一个应用:Hello World都不简单

Django的“项目-应用”结构一开始让我很懵(Go里直接main.go走起)。按官方文档敲命令:

# 创建项目
django-admin startproject gov_platform .

# 创建应用(注意最后的点!很多人漏掉导致路径错乱)
python manage.py startapp data_show

目录结构长这样:

gov_platform/
├── manage.py
├── gov_platform/       # 项目配置
│   ├── __init__.py
│   ├── settings.py     # ⚠️重点!数据库、中间件都在这
│   ├── urls.py
│   └── wsgi.py
└── data_show/          # 你的业务代码
    ├── migrations/
    ├── models.py       # 数据库表定义
    ├── views.py        # 处理请求
    └── ...

这时候我犯了个低级错误:把业务逻辑写在gov_platform/views.py里。结果第二天Code Review被组长骂:“你这是要把settings.py变成单体应用吗?” 正确姿势是每个功能拆成独立app,方便后期解耦。

数据库设计:别学我用SQLite上线

因为赶时间,我本地用SQLite快速开发(Django默认配置)。models.py写了三个表:

# data_show/models.py
from django.db import models

class Department(models.Model):
    name = models.CharField(max_length=100, unique=True)
    code = models.CharField(max_length=20, unique=True)

class DataRecord(models.Model):
    dept = models.ForeignKey(Department, on_delete=models.CASCADE)
    value = models.DecimalField(max_digits=10, decimal_places=2)
    report_date = models.DateField()
    
    class Meta:
        # 联合唯一索引!防重复上报
        unique_together = ('dept', 'report_date')

🚨 血泪教训:本地跑得好好的,部署到测试环境时运维说:“生产用MySQL,你这decimal字段精度不够!” 原来SQLite对decimal支持不严格,MySQL直接报错。永远用生产同款数据库开发!现在我们团队强制要求Docker Compose启动MySQL容器开发。

迁移命令很简单:

python manage.py makemigrations
python manage.py migrate

但要注意:makemigrations生成的文件要提交到Git!否则其他开发者拉代码后数据库结构对不上,又是一场灾难。

视图与模板:告别JSON,拥抱HTML

作为Go开发者,我习惯返回JSON(毕竟前后端分离是常态)。但这次甲方要求“传统页面”,得用Django模板。views.py这么写:

# data_show/views.py
from django.shortcuts import render
from .models import Department, DataRecord

def dashboard(request):
    # 预加载部门数据(避免N+1查询!)
    records = DataRecord.objects.select_related('dept').all()
    return render(request, 'dashboard.html', {'records': records})

模板文件放在data_show/templates/dashboard.html

<!-- 注意:Django模板语法和Go的text/template完全不同 -->
{% for record in records %}
  <div>
    {{ record.dept.name }}: {{ record.value }}
  </div>
{% endfor %}

💡 性能提示select_related相当于SQL的JOIN,避免循环查数据库。我第一次没加,测试环境100条数据就慢得像蜗牛——这要是Go里早用GORM预加载了,但在Django里得主动调用。

静态文件:CSS/JS加载失败的真相

页面样式乱成狗,F12一看404。原来Django对静态文件有特殊处理!需要在settings.py配置:

# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / "static",  # 开发时静态文件目录
]
STATIC_ROOT = BASE_DIR / "staticfiles"  # collectstatic输出目录

然后执行:

# 收集所有app的静态文件到STATIC_ROOT
python manage.py collectstatic

🤦‍♂️ 踩坑实录:运维部署时忘了跑collectstatic,线上CSS全挂。从此我们CI流程加了这一步,还写了检查脚本——小厂没SRE,只能自己当运维。

部署上线:从localhost到公网

终于到了最刺激的环节!我们用Nginx + Gunicorn(别用Django自带server,那是玩具)。

1. 安装Gunicorn

pip install gunicorn

2. 启动命令

# --bind 绑定内网IP,--workers 根据CPU核数调整
gunicorn --bind 0.0.0.0:8000 gov_platform.wsgi:application

3. Nginx反向代理配置

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 静态文件直接由Nginx处理(更快!)
    location /static/ {
        alias /path/to/staticfiles/;
    }
}

🔒 安全提醒:别把DEBUG=True放线上!我们曾因DEBUG=True导致数据库密码泄露(Django错误页会打印环境变量)。现在部署脚本第一行就是sed -i 's/DEBUG = True/DEBUG = False/' settings.py

对比Go:Django的取舍之道

折腾完这个项目,我对Django有了新认识。做个简单对比:

维度 Django (Python) Gin (Go)
开发速度 ⭐⭐⭐⭐⭐ (Admin/ORM开箱即用) ⭐⭐ (需手写大量胶水代码)
性能 ⭐⭐ (Python解释型语言瓶颈) ⭐⭐⭐⭐⭐ (编译型,高并发利器)
学习曲线 ⭐⭐⭐ (约定大于配置) ⭐⭐ (简洁但需理解中间件)
生态 ⭐⭐⭐⭐ (Web领域无敌) ⭐⭐⭐ (微服务生态强)

说白了:Django适合快速交付业务系统,Go适合构建高性能基础设施。就像我们公司——内部管理后台用Django,用户交易核心用Go。

写在最后:代码人生的另一种可能

凌晨三点,当我看到政府验收邮件里写着“系统运行稳定”时,突然有点感慨。以前总觉得写Go才叫“正经程序员”,Django不过是脚本玩具。但这次经历让我明白:技术没有高低贵贱,解决问题才是王道

就像上周团建,领导说:“别总想着重构,先把需求做完。” 是啊,在小厂生存,既要能写高并发架构,也要能撸起袖子搭个Django站。毕竟——

面试题可以背,但线上Bug得亲手修;
Go可以吹性能,但甲方爸爸要的是明天上线。

如果你也在被 deadline 追着跑,不妨试试Django。它可能不够酷,但足够稳。就像北京早高峰的地铁——挤是挤了点,但总能把你送到目的地。


P.S. 本文代码已脱敏上传GitHub(私信我拿链接),包含Dockerfile和Nginx配置。下次跳槽面试被问Django,至少能说出“我在生产环境用过”而不是“看过教程”。毕竟在这个卷成麻花的行业,真实的项目经验,永远比八股文值钱

(完)

作者:某小厂后端,坐标北京,通勤1h,正在用Django救火的同时偷偷学Rust。技术博客更新不定期,但保证全是踩坑实录。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝