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

半个架构师
2025-12-18 14:48
阅读 1233

上周五晚上十一点,我正瘫在成都温江家里那张从宜家搬回来的破沙发上,一边啃着冒菜一边刷GitHub Trending。突然收到前同事小王的消息:“哥,能帮忙看看Django怎么搭吗?明天面试要手撕一个后台。” 我叹了口气——这已经是本月第三个问我Django的了。看来“Python + 面试题挑战”这套组合拳,真是让不少兄弟夜不能寐。

作为一个靠远程接单吃饭的独立开发者,我其实挺理解这种焦虑的。自由职业听起来潇洒,但每次投简历、谈项目,客户第一句永远是:“你用过Django吗?能快速搭个MVP出来不?” 尤其是成都这边,不少初创公司产品经理(对,就是那种张口闭口“用户心智”的哥们)总想一周内上线一个“对标Notion的协作产品”,还要求支持实时协同、多端同步、数据加密……兄弟,你预算才两万块啊!

不过话说回来,Django确实是个好东西。它不像Flask那样“自由到让你裸奔”,也不像FastAPI那样对新手有点门槛。Django自带Admin、ORM、认证系统,开箱即用,特别适合快速验证产品想法。今天我就带大家从零搭一个最简但安全可用的Django网站——不是那种教程里跑通就完事的玩具,而是能真正拿去跟客户吹牛、甚至部署上线的架子。

别再用python manage.py runserver上生产了!

很多教程一上来就让你执行:

django-admin startproject mysite
cd mysite
python manage.py runserver

然后浏览器打开 127.0.0.1:8000,看到那个火箭图标就欢呼“搞定!”。打住!如果你真这么干,运维半夜打电话骂你的时候别说我没提醒。

runserver 是开发服务器,性能差、不支持并发、没有HTTPS,更别说WAF、日志监控这些生产环境标配了。我去年双11帮一家电商做紧急支援,他们测试环境直接用 runserver 对外暴露,结果被扫出一堆SQL注入漏洞——虽然Django ORM本身防注入,但前端传参没校验,加上中间件配置错误,差点把用户订单表给拖库了。

所以,从第一天起,我们就得按生产标准来搭。

安全第一:环境隔离与依赖管理

先建个虚拟环境,这是基本礼仪:

python -m venv .venv
source .venv/bin/activate  # Linux/Mac
# Windows用:.venv\Scripts\activate
pip install django gunicorn python-decouple

注意我装了 python-decouple —— 这玩意能让你把敏感配置(比如SECRET_KEY、数据库密码)从代码里剥离,存到 .env 文件里。千万别把 settings.py 里的密钥直接提交到GitHub,不然哪天你的AWS账单会告诉你什么叫“社会性死亡”。

.env 文件内容示例:

DEBUG=False
SECRET_KEY=your-super-secret-key-here
DATABASE_URL=sqlite:///db.sqlite3

然后在 settings.py 里这样读:

from decouple import config

DEBUG = config('DEBUG', default=False, cast=bool)
SECRET_KEY = config('SECRET_KEY')
DATABASES = {
    'default': config('DATABASE_URL', cast=db_url)
}

对了,记得把 .env 加到 .gitignore 里!

数据库设计:别让产品经理改需求改到你哭

Django的ORM很香,但香归香,表结构设计还是要谨慎。我见过太多人为了赶deadline,直接让模型字段叫 data, info, extra,结果后期加索引、改类型时欲哭无泪。

假设我们要做一个简单的博客(毕竟每个教程都得有个博客),模型可以这样写:

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

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)  # 用于URL友好
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_published = models.BooleanField(default=False)  # 草稿/发布状态

    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['slug']),
            models.Index(fields=['is_published', 'created_at'])
        ]

几个关键点:

  • slug 字段确保URL可读且唯一
  • is_published 控制草稿和正式文章
  • 显式声明数据库索引,避免后期慢查询
  • 时间字段自动维护,别手写 datetime.now()

前后端分离?别急,先搞清楚你要做什么产品

现在很多教程一上来就喊“Django只做API,前端用Vue/React”,搞得好像不用前后端分离就不够 modern。但现实是:如果你的产品只是个内部管理系统、或者一个简单的展示型网站,硬拆前后端反而增加复杂度。

Django自带的模板引擎(Django Templates)完全够用,而且省去了跨域、鉴权、部署两套服务的麻烦。我最近接的一个政府数据可视化项目,客户明确要求“所有代码必须部署在同一台服务器”,这时候用模板渲染反而更稳。

当然,如果你要做的是富交互应用(比如在线文档、实时聊天),那还是乖乖上DRF(Django REST Framework)+ Vue 吧。不过那是另一篇文的事了。

这里我们先用原生模板做个首页:

<!-- templates/home.html -->
<!DOCTYPE html>
<html>
<head>
    <title>我的第一个Django站</title>
</head>
<body>
    <h1>欢迎来到{{ site_name }}</h1>
    {% for post in posts %}
        <div>
            <h2><a href="/post/{{ post.slug }}">{{ post.title }}</a></h2>
            <p>{{ post.created_at|date:"Y-m-d" }}</p>
        </div>
    {% endfor %}
    
    <!-- 注意:这里暂时没引入JS,但实际项目中你会需要 -->
    <script>
        // 比如埋点、交互逻辑等
        console.log("Hello from Javascript!");
    </script>
</body>
</html>

安全加固:那些你可能忽略的细节

Django默认已经做了很多安全防护(比如CSRF、XSS转义),但还不够。以下是我每次新建项目必加的配置:

# settings.py 安全部分补充
SECURE_HSTS_SECONDS = 31536000  # 强制HTTPS一年
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_SSL_REDIRECT = True      # HTTP自动跳HTTPS
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'        # 防止点击劫持

# 允许的主机(生产环境必须设!)
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

# 密码强度(如果用Django Auth)
AUTH_PASSWORD_VALIDATORS = [
    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {'min_length': 10}},
]

另外,永远不要在前端暴露敏感逻辑。比如有人喜欢用JavaScript判断用户权限然后隐藏按钮——这等于把后门钥匙挂在门口。权限校验必须在后端做!

部署:用Gunicorn + Nginx 才是正道

本地跑通只是开始,部署才是地狱难度。我推荐的最小可行部署方案:

  • Gunicorn:Python WSGI HTTP Server,比 runserver 稳得多
  • Nginx:反向代理、静态文件服务、SSL终止

启动脚本 start.sh

#!/bin/bash
source .venv/bin/activate
gunicorn --bind 0.0.0.0:8000 mysite.wsgi:application --workers 3

Nginx配置片段:

server {
    listen 80;
    server_name yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

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

    location /static/ {
        alias /path/to/collected_static/;
    }
}

记得运行 python manage.py collectstatic 收集静态文件!

总结:Django不是银弹,但足够让你少踩坑

说实话,作为一个常年和deadline搏斗的独立开发者,我特别感激Django这种“约定优于配置”的框架。它逼你写出结构清晰、安全合规的代码,而不是像某些Node.js项目一样,三天写完,三个月修bug。

如果你正在准备“Python 面试题挑战”,记住:面试官不只想看你跑通demo,更想看你是否考虑过安全性、可维护性、部署成本。比如你可以聊聊:

  • 为什么用 SlugField 而不是直接ID做URL?
  • 如何防止CSRF攻击?
  • 数据库连接池怎么配?
  • 日志怎么集中收集?

这些细节,才是区分“会写代码”和“能交付产品”的关键。

最后,别忘了:技术只是工具,产品才是目的。我见过太多开发者沉迷于架构炫技,结果做出来的东西用户根本不用。上周我还在群里吐槽一个朋友,他花了两周给个人博客加上WebSocket实时评论,结果月活就仨人——其中俩还是他自己小号。

好了,教程就到这里。如果你照着做完了,恭喜你,你已经超过了80%只会在本地跑 runserver 的Django新手。现在,去泡杯茶,打开VS Code,开始你的第一个真正可用的Python网站吧。

(P.S. 成都的春天真舒服,希望你写代码的时候窗外也有花香。)

评论 0

最热最新
暂无评论
半个架构师Lv.1
0
影响力
0
文章
0
粉丝