# 静态文件

# 存储路径

在 Django 项目中使用静态文件、模板文件时,Django 默认会到每个 app 目录的 static、templates 子目录下寻找该文件。因此应该通过该文件在 static、templates 目录下的相对路径来引用它。

  • 不应该使用绝对路径,否则改变项目的部署路径时就需要修改源代码中引用的路径。
  • 如果多个目录下存在路径相同的文件,则只会采用第一个找到的文件。
  • 目录结构示例:
    django_site
    ├── ...
    ├── static
    ├── templates
    └── app1
        ├── ...
        ├── static
        │   ├── login.html      # 调用该文件的相对路径为 'login.html' 
        │   └── app1            # 为了避免不同 app 的文件冲突,建议根据每个 app 的名称再划分一层子目录
        │       └── index.html  # 调用该文件的相对路径为 'app1/index.html' 
        └── templates
            └── index.html
    

# 配置

使用静态文件、模板文件时,应该在 settings.py 中加入如下配置:

TEMPLATES = [                                                           # 配置视图模板
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',   # 模板引擎
        'APP_DIRS': True,                                               # 是否在每个 app 的 templates 目录下寻找模板文件
        'DIRS': [os.path.join(BASE_DIR, 'templates')],                  # 除了 APP_DIRS 之外,加入其它寻找模板文件的目录
        'OPTIONS': {                                                    # 传给模板引擎的参数
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

STATIC_URL  = '/static/'                         # 如果 HTTP 请求指向的 URL 以它开头,则视作请求静态文件
STATIC_ROOT = os.path.join(BASE_DIR, 'static')   # 静态文件被收集之后的存放目录
# STATICFILES_DIRS = [                           # 除了 APP_DIRS 之外,加入其它寻找静态文件的目录
#     os.path.join(BASE_DIR, 'static'),
# ]

# MEDIA_URL = "/media/"
# MEDIA_ROOT = os.path.join(BASE_DIR, "media")   # 设置 media 目录,通常用于存放用户上传的文件
  • 调试模式下,Django 收到指向 STATIC_URL 的 HTTP 请求时,会自动寻找静态文件作出 HTTP 响应,但是性能较低。
  • 关闭调试模式时,Django 不会处理静态文件,需要先执行 python manage.py collectstatic ,寻找所有静态文件并拷贝到 STATIC_ROOT 目录下,然后使用 Nginx 等 Web 服务器代理该目录下的静态文件。

# template

Django 支持将 HTML 文件抽象为 HTML 模板文件,称为 template ,从而灵活地渲染 HTML 文件。

  • 模板文件采用 Django 自带的 DTL(Django Template Language )模板语言编写,与 Jinja 的语法相似。
  • 模板文件的扩展名也是 .html 。

# 基本用法

  • 编写一个简单的 template 文件:

    {% load static my_template_tags %}  # 在模板文件的开头使用 load 标签,导入一些标签、过滤器
    
    <h1>{{ str1 }}</h1>                 # 插入一个名为 str1 的变量的值
    {{ str1|first|upper }}              # 可以使用一些基于管道符的过滤器,修改变量的值
    
    {% if debug  %}                     # 通过 if 标签进行条件判断
      <h1> Hello World! </h1>
    {% else %}
      <h1>{{ str1 }}</h1>
    {% endif %}
    
    # 用 static 标签引用 STATIC_ROOT 目录下的静态文件。它会将静态文件从相对路径转换成绝对路径,例如 href="/static/app1/css/style.css"
    <link rel="stylesheet" type="text/css" href="{% static 'app1/css/style.css' %}">
    
  • 使用模板文件时,传入一些参数,就可以渲染出最终的 HTML 文件。例如下方的视图函数:

    from django.shortcuts import render
    
    def test(request):
        context          = {}           # 创建一个上下文字典 context ,包含一些变量,用于渲染模板文件
        context['str1'] = 'Hello'
        return render(request, 'my_template.html', context)
    
  • 在模板文件中使用 post 表单时,总是应该加上 {% csrf_token %} 标签,从而避免 CSRF 攻击。如下:

    <form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
    <input type="submit" value="Vote">
    </form>