静态目录
配置静态目录
-
STATIC_URL
配置的静态目录位于项目根目录下的static
文件夹,用于保存项目公共的静态资源。 -
STATICFILES_DIRS
配置的是项目应用的静态目录,位于应用根目录下的static
文件夹,用于保存不同应用的静态资源。
$ vim gamsite/settings.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# 应用静态文件夹
STATIC_URL = '/static/'
# 项目静态文件夹
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
使用静态目录
- 配置静态目录后可在模板中使用配置静态目录替代文件路径
- 模板中加载应用的静态资源
{% load static %}
{% load staticfiles%}
- 模板引用应用静态资源
{% static 'flename.ext' %}
- 模板中直接定义定义静态资源路径
<img src="/static/images/logo.png" />
模板引擎(DTL, Django Template Language)
- Django使用模板系统(Template System)实现Python代码和HTML代码分离
- Django的模板文件中包含两部分分别是HTML代码和逻辑控制代码
模板配置选项
- 项目全局配置文件
settings.py
文件中的TEMPLATES
配置值是一个列表,分别针对各种模板引擎进行单独配置。
$ vim gamesite/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'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',
],
},
},
]
模板引擎配置是一个字典类型,具体的配置项包括
配置项 | 描述 |
---|---|
BACKEND | 后端模板引擎类型,值为Python路径指向实现Django模板后端API的模板引擎类。 |
DIRS | 模板源文件目录列表,模板引擎按列表顺序查找模板文件,即模板加载目录。 |
APP_DIRS | 是否在安装的应用中查找模板,默认为True表示模板引擎会在INSTALLED_APPS 应用中查找名为templates 的子目录。 |
OPTIONS | 选项参数 |
Django内置的后端模板引擎类BACKEND
django.template.backends.django.DjangoTemplates
django.template.backends.jinja2.Jinja2
模板加载目录
- 在项目根目录下创建
templates
文件夹用于存放公共的主模板,然后设置DIRS
选项。 - 在应用根目录下创建
templates
文件夹用于存放应用模板,默认模板引擎会加载此目录下的模板文件。
$ mkdir /gamesite/templates
$ vim /gamesite/gamesite/settings.py
import os
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates')
],
'APP_DIRS': True,
'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',
],
},
},
]
- 使用
loader.get_template
函数会优先从项目模板目录下取查找指定目录,若没有则会到应用下的模板目录中查找指定模板。
$ vim backend/views.py
from django import loader
from django.http import HttpResponse
def test(request):
tpl = loader.get_template("test.html")
dict = {}
dict["name"] = "alice"
html = tpl.render(request=request, context=dict)
return HttpResponse(html)
-
django.shortcuts
快捷方法模块中提供了render()
函数用于加载模板、创建上下文、渲染模板,同时会创建HttpResponse
响应对象。 -
render()
快捷函数返回的是一个HttpResponse
对象
$ vim backend/views.py
import datetime
from django.shortcuts import render
def test(request):
return render(request, "test.html", {"current_datetime":datetime.datetime.now()})
模板上下文变量
- 从
django
模块中加载template
对象 - 创建模板字符串
- 使用
template
对象创建Template
模板对象 - 使用
template
对象创建模板Context
上下文对象 - 调用模板对象的
render(context)
渲染模板并传递上下文对象到模板中使用
$ cd gamesite
$ python3 manage.py shell
>>> from django import template
>>> tpl = template.Template("hello, {{ name }}")
>>> ctx = template.Context({"name":"alice"})
>>> print(tpl.render(ctx)
hello, alice
模板变量
- 文本插值,模板系统中使用成对双花括号包裹的文本表示变量
{{ varname }}
,表示将指定变量的值插入到这里。
{{ varname }}
- 模板标签,模板系统中使用成对花括号和成对百分号包裹的文本表示模板标签
{% tagname %}
{% tagname %}
- 过滤器,模板系统中使用
{{ varname | filter:"parameter" }}
对变量进行过滤
{{ varname | filter:"parameter" }}
模板标签
- 模板注释标签
模板中使用{# #}
作为单行注释标签,使用{% comment %}...{% endcomment %}
作为多行注释标签
模板引入
- 模板中可使用
include
模板标签引用公共模板的内容 -
include
模板标签的参数可以是待引入模板的名称,也可以是变量,或是硬编码的字符串。
$ vim templates/test.html
{% include "nav.html" %}
模板继承
模板继承是先构造基础框架模板,而后在其子模板中对父模板中所定义的区块的内容进行重载。
- 模板继承分为两种块片段分别是父模板和子模板
- 模板继承时需要在父模板中使用成对的
block
模板标签定义分块,子模板会覆盖分块中的内容。 - 模板继承时子模块中会使用
extends
模板标签声明需继承的父模板名称,同时使用成对的block
模板标签创建需要覆盖父模板分块区域的内容。
$ vim templates/layout.html
{% block block_name %}
super layout content area
{% endblock %}
$ vim templates/home.html
{% extends layout.html %}
{% block block_name %}
child content extends layout
{% endblock %}
模板规划
对游戏管理后台首页界面使用模板引用和继承,提取出模板中公共部分。
- 在
templates
目录下创建particle
文件用于存放公共模板和父模板 - 后台页面规划出名为
layout.html
的父模板用于定义UI的布局框架结构 - 从
layout.html
布局框架中提取频繁使用的公共模块按需添加
原始模板内容
$ vim templates/home/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>GM游戏管理平台</title>
<link href="https://cdn.bootcdn.net/ajax/libs/tailwindcss/1.4.6/tailwind.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
</head>
<body>
<!--container-->
<div class="mx-auto bg-gray-100" x-data="{dropdown:false, aside:true, menu:false}">
<!--screen-->
<div class="min-h-screen flex flex-col">
<!--header-->
<header class="relative bg-black text-white flex items-center justify-between px-4 py-1">
<!--logo-->
<div class="inline-flex items-center">
<i class="fas fa-bars" @click="aside=!aside"></i>
</div>
<!--avatar-->
<div class="flex flex-row items-center justify-center">
<img src="http://source.unsplash.com/100x100/?avatar" class="h-8 h-8 rounded-full">
<span class="p-2 hidden md:block text-xs">Admin</span>
<i class="fas fa-caret-down" @click="dropdown=!dropdown"></i>
</div>
<!--downdrop-->
<div class="absolute right-0 mt-16 mr-2 bg-white border rounded shadow-xl" x-show="dropdown">
<ul class="list-reset divide-y text-gray-700 text-xs">
<li>
<a href="" class="no-underline block px-4 py-2 hover:bg-gray-100">个人资料</a>
</li>
<li>
<a href="{% url 'backend:logout' %}" class="no-underline block px-4 py-2 hover:bg-gray-100">安全退出</a>
</li>
</ul>
</div>
</header>
<!--main-->
<main class="flex-1 flex">
<!--mini-->
<nav class="p-2 bg-black text-white flex flex-col items-center justify-star" x-show="!aside">
<span class="mb-2 last:mb-0 w-8 h-8 rounded-full hover:bg-gray-900 flex items-center justify-center" @click="aside=!aside">
<i class="fas fa-users"></i>
</span>
<span class="mb-2 last:mb-0 w-8 h-8 rounded-full hover:bg-gray-900 flex items-center justify-center" @click="aside=!aside">
<i class="fas fa-cogs"></i>
</span>
</nav>
<!--sidebar-->
<aside class="bg-gray-900 text-white hidden md:block lg:block" x-show="aside">
<!--nav-->
<ul class="list-reset flex flex-col divide-y divide-gray-900 text-gray-400">
<li class="w-full h-full">
<!--level1-->
<div class="px-2 py-3 flex items-center justify-between bg-gray-800 text-base">
<a href="" class="no-underline block flex items-center">
<i class="fas fa-bug"></i>
<span class="ml-1 w-48">一级菜单</span>
</a>
<i class="fas fa-angle-right" @click="menu=!menu"></i>
</div>
<!--level2-->
<ul class="list-reset flex flex-col divide-y divide-gray-800 text-sm" x-show="menu">
<li class="w-full h-full">
<div class="py-2 pl-4 pr-2 flex items-center justify-between">
<a href="" class="no-underline block">
<i class="fas fa-caret-right"></i>
<span class="ml-1">二级菜单</span>
</a>
<i class="fas fa-angle-right"></i>
</div>
</li>
<li class="w-full h-full">
<div class="py-2 pl-4 pr-2 flex items-center justify-between text-gray-500">
<a href="" class="no-underline block text-sm">
<i class="fas fa-caret-right"></i>
<span class="ml-1">二级菜单</span>
</a>
<i class="fas fa-angle-right"></i>
</div>
</li>
</ul>
</li>
</ul>
</aside>
<!--content-->
<div class="flex-1 p-4 overflow-hidden">
<!--card-->
<div class="my-2 border border-solid border-gray-200 rounded bg-white shadow-sm w-full">
<div class="px-2 py-3 border-b border-gray-200 font-base">卡片标题</div>
<div class="p-4 text-sm">卡片内容</div>
</div>
</div>
</main>
<!--footer-->
<footer></footer>
</div>
</div>
</body>
</html>
创建公共布局框架模板
$ vim templates/particle/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
{% include 'particle/head.html' %}
</head>
<body>
<!--container-->
<div class="mx-auto bg-gray-100" x-data="{dropdown:false, aside:true, menu:false}">
<!--screen-->
<div class="min-h-screen flex flex-col">
<!--header-->
{% include 'particle/header.html' %}
<!--main-->
<main class="flex-1 flex">
<!--mini-->
{% include 'particle/nav.html' %}
<!--sidebar-->
{% include 'particle/aside.html' %}
<!--content-->
<div class="flex-1 p-4 overflow-hidden">
{% block content %}
{% endblock %}
</div>
</main>
<!--footer-->
{% block footer %}
<footer></footer>
{% endblock %}
</div>
</div>
</body>
</html>
创建公共页头模板
$ vim templates/particle/head.html
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>GM游戏管理平台</title>
<link href="https://cdn.bootcdn.net/ajax/libs/tailwindcss/1.4.6/tailwind.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>
创建公共顶部模板
$ vim templates/particle/nav.html
<nav class="p-2 bg-black text-white flex flex-col items-center justify-star" x-show="!aside">
<span class="mb-2 last:mb-0 w-8 h-8 rounded-full hover:bg-gray-900 flex items-center justify-center" @click="aside=!aside">
<i class="fas fa-users"></i>
</span>
<span class="mb-2 last:mb-0 w-8 h-8 rounded-full hover:bg-gray-900 flex items-center justify-center" @click="aside=!aside">
<i class="fas fa-cogs"></i>
</span>
</nav>
创建公共侧边栏模板
$ vim templates/particle/aside.html
<aside class="bg-gray-900 text-white hidden md:block lg:block" x-show="aside">
<!--nav-->
<ul class="list-reset flex flex-col divide-y divide-gray-900 text-gray-400">
<li class="w-full h-full">
<!--level1-->
<div class="px-2 py-3 flex items-center justify-between bg-gray-800 text-base">
<a href="" class="no-underline block flex items-center">
<i class="fas fa-bug"></i>
<span class="ml-1 w-48">一级菜单</span>
</a>
<i class="fas fa-angle-right" @click="menu=!menu"></i>
</div>
<!--level2-->
<ul class="list-reset flex flex-col divide-y divide-gray-800 text-sm" x-show="menu">
<li class="w-full h-full">
<div class="py-2 pl-4 pr-2 flex items-center justify-between">
<a href="" class="no-underline block">
<i class="fas fa-caret-right"></i>
<span class="ml-1">二级菜单</span>
</a>
<i class="fas fa-angle-right"></i>
</div>
</li>
<li class="w-full h-full">
<div class="py-2 pl-4 pr-2 flex items-center justify-between text-gray-500">
<a href="" class="no-underline block text-sm">
<i class="fas fa-caret-right"></i>
<span class="ml-1">二级菜单</span>
</a>
<i class="fas fa-angle-right"></i>
</div>
</li>
</ul>
</li>
</ul>
</aside>
后台首页作为子模板继承自layout
布局父模板,并覆写content
区块分组内容。
$ vim templates/home/index.html
{% extends 'particle/layout.html' %}
{% block content %}
<!--card-->
<div class="my-2 border border-solid border-gray-200 rounded bg-white shadow-sm w-full">
<div class="px-2 py-3 border-b border-gray-200 font-base">卡片标题</div>
<div class="p-4 text-sm">卡片内容</div>
</div>
{% endblock %}