一、.env 文件与 settings.py 结合
Q1: .env 文件如何与 settings.py 结合使用?
A: 需要两步:
加载 .env 到环境变量:在
settings.py顶部添加from dotenv import load_dotenv load_dotenv()读取环境变量:使用
os.environ.get('变量名')读取import os SECRET_KEY = os.environ.get('SECRET_KEY') DEBUG = os.environ.get('DEBUG', 'False') == 'True'
Q2: 环境变量读取的 os.environ.get() 有两个参数是什么意思?
A: 第二个参数是默认值。
os.environ.get("ALLOWED_HOSTS", "")
# ↑ 变量名 ↑ 默认值(变量不存在时返回这个)
当环境变量不存在时:
- 不写第二个参数 → 返回
None - 写
""→ 返回空字符串(避免None.split()报错) - 写
"localhost"→ 返回 localhost
Q3: 环境变量读出来是什么类型?
A: 永远是字符串,无论 .env 里写什么。
# .env
DEBUG=True
PORT=8000
os.environ.get("DEBUG") # → "True" (字符串,不是布尔值)
os.environ.get("PORT") # → "8000" (字符串,不是整数)
必须手动转换:
DEBUG = os.environ.get("DEBUG") == 'True' # 字符串 → 布尔值
PORT = int(os.environ.get("PORT", "8000")) # 字符串 → 整数
ALLOWED_HOSTS = os.environ.get("HOSTS").split(',') # 字符串 → 列表
Q4: 环境变量命名有什么规范?
A:
- 全大写:
DB_NAME而不是db_name - 下划线分隔:
SECRET_KEY而不是secret-key - 语义清晰:带前缀如
DB_、AWS_避免冲突 - 保持一致:代码里读的名字必须和 .env 里写的完全一致
注意:代码中 os.environ.get('POSTGRES_DB') 和 .env 里的 DB_NAME 不匹配,会导致读取失败。
二、settings.py 核心配置解释
Q5: BASE_DIR = Path(__file__).resolve().parent.parent 是什么意思?
A: 获取项目根目录的绝对路径。
项目根目录/ ← BASE_DIR 指向这里
├── django_gallery/ ← settings.py 在这里
│ └── settings.py ← __file__
├── manage.py
└── ...
Path(__file__) → settings.py 路径
.resolve() → 转成绝对路径
.parent → django_gallery/
.parent → 项目根目录/
用于构建其他路径:
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Q6: STATIC_URL = 'static/' 为什么没有 BASE_DIR?
A: 因为 STATIC_URL 是 URL 路径(浏览器访问用),不是文件系统路径。
| 配置 | 类型 | 示例 |
|---|---|---|
STATIC_URL | URL 路径 | /static/ 或 https://cdn.com/static/ |
STATIC_ROOT | 文件路径 | C:\django\project\staticfiles |
流程:
用户访问 /static/css/style.css
↓
Django/Nginx 去 STATIC_ROOT 找实际文件
↓
C:\django\project\staticfiles\css\style.css
Q7: os.path.join() 是什么?
A: 智能拼接文件路径,自动适应操作系统。
import os
os.path.join('folder', 'file.txt')
# Windows: 'folder\file.txt'
# Linux/Mac: 'folder/file.txt'
对比新写法(推荐):
# 老写法
os.path.join(BASE_DIR, 'staticfiles')
# 新写法(Path 对象)
BASE_DIR / 'staticfiles'
Q8: DATABASES 配置里的 os.environ.get('POSTGRES_DB') 是什么意思?
A: 从环境变量读取数据库配置,避免密码硬编码。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('POSTGRES_DB'),
'USER': os.environ.get('POSTGRES_USER'),
'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
}
}
安全原因:密码写入代码会被 Git 记录,用环境变量更安全。
三、核心安全概念
Q9: SECRET_KEY 是什么?能干什么?
A: Django 的加密签名密钥,用于:
- Session 验证:生成/验证用户登录状态
- 密码重置 Token:生成"忘记密码"链接
- CSRF 保护:表单安全验证
- 消息框架:防止提示信息被篡改
泄露后果:
- 攻击者可伪造任意用户身份(包括管理员)
- 可提前预知密码重置链接
- 可绕过 CSRF 保护
注意:以 django-insecure- 开头的是示例密钥,生产环境必须更换!
Q10: 如何生成新的 SECRET_KEY?
A:
python -c "import secrets; print(secrets.token_urlsafe(50))"
生成后写入 .env:
SECRET_KEY=aB3xK9mP2vL5nQ8wR4tY7uI0oP1jH6gF3dS2aZ9xC4vB7nM1kL8jH3gF5dS2aZ
不要带 django-insecure- 前缀。
Q11: DEBUG=True 和 False 的区别?为什么改成 False 图片裂开了?
A:
| 特性 | DEBUG=True | DEBUG=False |
|---|---|---|
| 错误页面 | 详细调试信息 | 友好错误页 |
| 静态/媒体文件服务 | ✅ Django 自动提供 | ❌ Django 不处理 |
| 安全性 | 低 | 高 |
图片裂开原因:DEBUG=False 时 Django 不再自动提供媒体文件,必须通过 Nginx 配置 location /media/ 来提供。
Nginx 配置:
location /media/ {
alias /home/deployer/django_gallery/media/; # MEDIA_ROOT 的实际路径
}
四、ALLOWED_HOSTS 配置
Q12: ALLOWED_HOSTS 列表如何用 env 文件写?
A: env 存字符串,代码转列表。
# .env
ALLOWED_HOSTS=eth1.me,www.eth1.me,localhost
# settings.py
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost').split(',')
处理空格(推荐):
ALLOWED_HOSTS = [
host.strip()
for host in os.environ.get('ALLOWED_HOSTS', '').split(',')
if host.strip()
]
Q13: 套了 Nginx 后 ALLOWED_HOSTS 要保留哪些?
A: 只保留域名,去掉 localhost 和 IP(除非有特殊需求)。
# 生产环境推荐
ALLOWED_HOSTS=eth1.me,www.eth1.me
注意:Nginx 必须配置 proxy_set_header Host $host,把域名转发给 Django。
五、S3 对象存储
Q14: 启用 S3 后哪些文件会上传?CSS 也会吗?
A: 两类文件:
| 类型 | 包含 | 上传时机 |
|---|---|---|
| 静态文件 | CSS、JS、图片、字体、admin 样式 | collectstatic 时批量上传 |
| 媒体文件 | 用户上传的图片、文档 | 实时上传 |
是的,CSS 会上传,属于静态文件的一部分。
Q15: 可以让 CSS 不上传 S3,只让媒体文件上传吗?
A: 可以,混合方案:
# settings.py
# 媒体文件 → S3
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
# 静态文件 → 本地(配合 Whitenoise)
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
STATIC_ROOT = BASE_DIR / 'staticfiles'
安装 Whitenoise:
pip install whitenoise
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # 加在这里
# ...
]
优势:静态文件不变、体积小,本地存储 + CDN 缓存即可;媒体文件动态增长,适合 S3。
六、其他实用命令
Q16: 如何查看 Django 版本?
django-admin --version
python -m django --version
pip show django
当前项目版本:5.2.8
Q17: 如何升级 Django?
# 升级到指定版本
pip install django==5.2.9
# 或修改 requirements.txt 后
pip install -r requirements.txt
# 升级后必须执行
python manage.py migrate
注意:跨大版本升级(如 5.2 → 6.0)前查看官方升级指南,先在开发环境测试。
七、快速检查清单
生产环境部署前检查
-
DEBUG=False -
SECRET_KEY已更换(非django-insecure-开头) -
ALLOWED_HOSTS只包含实际域名 - 数据库配置读取环境变量
- 运行了
collectstatic - Nginx 配置了
/static/和/media/ -
.env文件已加入.gitignore
八、核心原则总结
- 敏感信息必须入 env:SECRET_KEY、密码、密钥
- 环境变量永远是字符串:需要手动转布尔值、整数、列表
- DEBUG=False 必须配 Nginx:Django 不再提供静态/媒体文件
- 变量名要完全一致:代码里
POSTGRES_DB和 .env 里DB_NAME对不上就失效 - 每个项目 SECRET_KEY 必须唯一:泄露 = 门户大开
文档生成时间:2026-02-20