一、.env 文件与 settings.py 结合

Q1: .env 文件如何与 settings.py 结合使用?

A: 需要两步:

  1. 加载 .env 到环境变量:在 settings.py 顶部添加

    from dotenv import load_dotenv
    load_dotenv()
    
  2. 读取环境变量:使用 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:

  1. 全大写DB_NAME 而不是 db_name
  2. 下划线分隔SECRET_KEY 而不是 secret-key
  3. 语义清晰:带前缀如 DB_AWS_ 避免冲突
  4. 保持一致:代码里读的名字必须和 .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_URLURL 路径(浏览器访问用),不是文件系统路径。

配置类型示例
STATIC_URLURL 路径/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 的加密签名密钥,用于:

  1. Session 验证:生成/验证用户登录状态
  2. 密码重置 Token:生成"忘记密码"链接
  3. CSRF 保护:表单安全验证
  4. 消息框架:防止提示信息被篡改

泄露后果

  • 攻击者可伪造任意用户身份(包括管理员)
  • 可提前预知密码重置链接
  • 可绕过 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=TrueDEBUG=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

八、核心原则总结

  1. 敏感信息必须入 env:SECRET_KEY、密码、密钥
  2. 环境变量永远是字符串:需要手动转布尔值、整数、列表
  3. DEBUG=False 必须配 Nginx:Django 不再提供静态/媒体文件
  4. 变量名要完全一致:代码里 POSTGRES_DB 和 .env 里 DB_NAME 对不上就失效
  5. 每个项目 SECRET_KEY 必须唯一:泄露 = 门户大开

文档生成时间:2026-02-20