Django入门教程:搭建你的第一个Python网站
上周五晚上十一点,我正瘫在成都温江家里那张从宜家搬回来的破沙发上,一边啃着冒菜一边刷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