Django笔记——模板

Django学习之模板

模板

​ 此处以DLT为例,DTL 是 Django Template Language 三个单词的缩写,也就是Django自带的模板语言。当然也可以配置Django支持Jinja2等其他模板引擎。

一、DTL与普通的HTML文件的区别

​ DTL模板是一种带有特殊语法的HTML文件,这个HTML文件可以被Django编译,可以传递参数进去,实现数据动态化。在编译完成后,生成一个普通的HTML文件,然后发送给客户端。

二、渲染模板

渲染模板有两种常用的方式

①render_to_string:

找到模板,然后将模板编译后渲染成Python的字符串格式。最后再通过 HttpResponse 类包装成一个 HttpResponse 对象返回回去。示例代码如下:

from django.template.loader import render_to_string
from django.http import HttpResponse
def book_detail(request,book_id): 
	html = render_to_string("detail.html")  
	return HttpResponse(html)

②render:
django还提供了一个更加简便的方式,直接将模板渲染成字符串 和包装成 HttpResponse 对象一步到位完成。示例代码如下:

from django.shortcuts import render
def index(request):
    return render(request, 'index.html')

三、模板查找路径配置

​ 在项目的 settings.py 文件中。有一个 TEMPLATES 配置,这个配置包含了模板引擎的配置,模板查找路径的配置,模板上下文的配置等。

​ 当创建一个新的Django应用时,需要将该应用添加到INSTALLED_APPS列表中,这个列表中的每个应用程序都会被Django自动发现,并且可以使用Django的ORM、admin界面等功能。

# Application definition
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "home", # 要对自己的app进行安装
]
  1. DIRS :这是一个列表,在这个列表中可以存放所有的模板路径,以后在视图中使用 render 或者 render_to_string 渲染模板的时候,会在这个列表的路径中查找模板。
  2. APP_DIRS :默认为 True ,这个设置为 True 后,会在 INSTALLED_APPS 的安装了的 APP 下的 templates 文件夹中查找模板。
  3. 查找顺序:比如代码 render(‘list.html’) 。先会在 DIRS 这个列表中依次查找路径下有没有这个模板,如果有,就返回。如果 DIRS 列表中所有的路径都没有找到,那么会先检查当前这个视图所处的 app 是否已经安装,如果已经安装了,那么就先在当前这个 app 下的 templates 文件夹中查找模板,如果没有找到,那么会在其他已经安装了的 app 中查找。如果所有路径下都没有找到,那么会抛出一个 TemplateDoesNotExist 的异常。
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates", # 模版引擎,可以换别的
        "DIRS": [BASE_DIR / 'templates']# 列表:存放所有的模板路径
        "APP_DIRS": True, # 这个设置为True后,会在APP自己的templates文件夹中查找模板
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

四、DTL模板语法

4.1 变量命名及使用
  1. 普通变量

    • 在视图中定义并传递给模板的简单变量(如字符串、数字等)可以直接在模板中通过 {{ variable_name }} 访问。
    • 示例:username = '哈哈' 可以在模板中用 {{ username }} 显示。
  2. 字典类型

    • 字典可以通过点(.)语法访问其键对应的值。
    • 示例:game = {'name': '第五人格', 'character': '调香师'} 可以在模板中用 {{ game.name }}{{ game.character }} 分别显示 '第五人格''调香师'
  3. 列表

    • 列表可以通过索引访问其中的元素,索引用点(.)和数字表示。
    • 示例:games = [{'name': '王者荣耀', 'character': '孙尚香'}, {'name': '原神', 'character': '宵宫'}] 可以在模板中用 {{ games.0 }} 访问第一个元素,用 {{ games.1.name }} 获取第二个元素中的 name 值。
  4. 对象属性

    • 对象的属性或方法可以通过点(.)语法访问。如果对象具有属性或无参数的方法,则可以直接在模板中使用该属性名或方法名。
    • 示例:定义了一个 Person 类,并创建其实例 person = Person('小红'),可以在模板中用 {{ person.realname }} 显示 '小红'

注意事项

  • 点(.)语法解析顺序

    1. 首先尝试作为字典的键进行查找。
    2. 如果未找到,则尝试作为对象的属性进行查找。
    3. 如果仍未找到,则尝试作为可索引对象的索引进行查找。
  • 不支持中括号访问:Django 模板语言不支持像 dict['key']list[1] 这样的中括号访问方式。

  • 避免与内置属性名冲突:当向字典添加键时,要确保键名不会覆盖字典的内置方法或属性(如 items, keys 等),否则会导致无法正常访问这些方法或属性。

# views.py
def info(request):
    # 1. 普通的变量
    username = '哈哈'
    # 2. 字典类型
    game = {'name': '第五人格', 'character': '调香师'}
    # 3. 列表
    games = [
        {'name': '王者荣耀', 'character': '孙尚香'},
        {'name': '原神', 'character': '宵宫'}
    ]
    # return render(request, 'info.html', context={'username': username, 'game': game, 'games': games})

    # 4.对象
    class Person:
        def __init__(self, realname):
            self.realname = realname

    context = {
        'username': username,
        'game': game,
        'games': games,
        'person': Person('小红')
    }
    return render(request, 'info.html', context=context)
# info.html
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>信息title>
head>
<body>
    <p>{{ username }}p>
    <p>游戏名称:{{ game.name }}p>
    <p>下标为0的游戏:{{ games.0 }}p>
    <p>下标为1的游戏的名称:{{ games.1.name }}p>
    <p>姓名为:{{ person.realname }}p>
body>
html>
4.2 常用的模板标签
4.2.1 if 标签

if 标签相当于 Python 中的 if 语句,有 elifelse 相对应,但是所有的标签都需要用标签符号 {% %} 进行包裹。 if 标签中可以使用 ==、!=、<、<=、>、>=、in、not in、is、is not 等判断运算符。

# if
def if_view(request):
    age = 18
    return render(request, 'if.html', context={'age': age})
{% if age > 18 %}
    <p>您已满18岁。 可以玩第五人格p>
{% elif age == 18 %}
    <p>您刚满18岁,需要先提交审核才能进入游戏p>
{% else %}
    <p>您未满18岁,不可以玩第五人格p>
{% endif %}
4.2.2 for…in… 标签

for...in... 类似于 Python 中的 for...in... 。可以遍历列表、元组、字符串、字典等一切可以遍历的对象。

# for : 这里的for没有break和continue
def for_view(request):
    # 1.列表
    games = [
        {'name': '王者荣耀', 'character': '孙尚香'},
        {'name': '原神', 'character': '宵宫'},
        {'name': 'lolm', 'character': '拉克丝'}
    ]
    # 2.字典
    person = {
        'realname': 'KFC大王',
        'age': 22,
        'height': 190
    }

    context = {
        'games': games,
        'person': person
    }
    return render(request, 'for.html', context=context)
{#1.列表#}
<table>
    <thead>
        <tr>
            <th>序号th>
            <th>游戏名th>
            <th>角色th>
        tr>    
    
    thead>
    <tbody>
        {% for game in games reversed %} {#加reversed相当于反向遍历#}
            <tr>
                <td>{{ forloop.counter }}td>
                <td>{{ game.name }}td>    
                <td>{{ game.character }}td>
            tr>
        {% endfor %}
    tbody>
table>
{#2.字典 for in person.items/keys/values #} 
<div>
    {% for key, value in person.items %}
        <p>{{ key }}:{{ value }}p>
    {% empty %}   {#在遍历的对象如果没有元素,会执行 empty 中的内容#}
     	<p>暂时没有用户p>
    {% endfor %}
div>

在 for 循环中,DTL 提供了一些变量可供使用:

  • forloop.counter :当前循环的下标。以1作为起始值。
  • forloop.counter0 :当前循环的下标。以0作为起始值。
  • forloop.revcounter :当前循环的反向下标值。比如列表有5个元素,那么第一次遍历这个 属性是等于5,第二次是4,以此类推。并且是以1作为最后一个元素的下标。
  • forloop.revcounter0 :类似于 forloop.revcounter 。不同的是最后一个元素的下标是从 0开始。
  • forloop.first :是否是第一次遍历。
  • forloop.last :是否是最后一次遍历。
  • forloop.parentloop :如果有多个循环嵌套,那么这个属性代表的是上一级的for循环。
4.1.3 with 标签

with标签在模板中临时定义变量,从而简化复杂的表达式或重复使用的值

# with
def with_view(request):
    context = {
        'games': [
            {'name': '王者荣耀', 'character': '孙尚香'},
            {'name': '原神', 'character': '宵宫'},
            {'name': 'lolm', 'character': '拉克丝'}
        ]
    }
    return render(request, 'with.html', context=context)
{% with ys=games.1 %}
{% with games.1 as ys %} {#写法二#}
    <p>{{ ys.name }}:{{ ys.character }}p>
{% endwith %}
  • 在 with 语句中定义的变量,只能在 {%with%}{%endwith%} 中使用,不能在这个标签外面使用。
  • 定义变量的时候,不能在等号左右两边留有空格。比如 {% with ys = games.1%} 是错误的。
4.1.4 url 标签

url标签根据定义在 urls.py 文件中的 URL 模式反向解析出对应的 URL,使模板代码更加简洁和易于维护

# views.py
# url
def url_view(request):
    return render(request, 'url.html')
# 用于url反转传参示例
def game_detail(request, game_id):
    return HttpResponse(f'您访问的游戏id是:{game_id}')
# urls.py
urlpatterns = [
    path('baidu', views.baidu, name='baidu'),
    path('url', views.url_view, name="url"),
    path('game/', views.game_detail, name="game_detail"),
] 
<a href="{% url 'baidu' %}">百度a>
# url反转,使用关键字参数
<a href="{% url 'game_detail' game_id=1 %}">游戏详情a>
# url反转,使用位置参数
<a href="{% url 'game_detail' 1 %}">游戏详情a>

更多标签请参考官方文档:https://docs.djangoproject.com/en/5.0/ref/templates/builtins/

4.3 过滤器
过滤器名称 作用描述及注意点
cut 作用:移除指定的子串。
注意点:该过滤器直接从字符串中移除指定的所有实例,不支持正则表达式。
date 作用:格式化日期时间。
注意点:需要确保传入的对象是日期或日期时间对象,否则会抛出错误。
default 作用:提供默认值,如果变量为空或未定义则使用该值。
注意点:适用于字符串、列表等类型,但不会对布尔值 False 起作用。
safe 作用:标记字符串为安全的,避免自动转义 HTML。
注意点:仅当您完全信任内容来源时使用,否则可能导致 XSS 攻击。
truncatechars 作用:截断字符数到指定长度,并在末尾添加省略号(…)。
注意点:包括省略号在内的总长度将等于指定的字符数。
add 作用:对两个参数执行加法操作。可应用于整数、浮点数、字符串和列表。
注意点:对于字符串,它会进行连接;对于列表,它会尝试拼接列表。不同类型的加法可能会导致意外结果。例如,数字与字符串相加会导致错误。
length 作用:返回列表、元组、字典、字符串等的长度。
注意点:对于非迭代对象(如整数)将引发模板语法错误。
capfirst 作用:将字符串的第一个字母转换为大写。
注意点:只影响第一个字母,其他字母不变。如果首字符不是字母,则保持原样。
lower 作用:将字符串转换为小写。
注意点:只影响ASCII字符集中的大小写字母。
upper 作用:将字符串转换为大写。
注意点:同样只影响ASCII字符集中的大小写字母。
slugify 作用:将字符串转换为 URL 友好的格式(只包含小写字母、数字和连字符)。
注意点:会移除所有非字母数字字符,并将空格替换为连字符。
slice 作用:对列表或字符串进行切片操作,类似于 Python 的切片语法。
注意点:切片索引必须有效,且不能超出范围。
join 作用:使用指定的分隔符连接列表中的元素为一个字符串。
注意点:列表中的元素应为字符串,否则可能需要先转换。
random 作用:从列表中随机选择一个元素。
注意点:每次渲染模板时都可能产生不同的输出。
escape 作用:转义字符串中的 HTML 特殊字符。
注意点:用于防止 XSS 攻击,确保用户输入的安全性。
linebreaks 作用:将换行符转换为
标签或

标签。
注意点:适合处理多行文本,但在某些情况下,可能需要手动调整样式以适应布局需求。

striptags 作用:去除所有 HTML 标签。
注意点:不会解析嵌套标签,简单地删除所有出现的标签。
# filter 过滤器
from datetime import datetime

def filter_view(request):
    greet = 'I love you, you love me.'
    items = ['apple', 'banana', 'cherry', 'date', 'elderberry']
    text = "Hello Django!"
    numbers = [1, 2, 3, 4, 5]
    context = {
        'greet': greet,
        'today': datetime.now(),
        'weather': '',
        'html': '

欢迎观看天气预报

'
, 'value': '北京欢迎您', 'number': 5, 'items': items, 'text': text, 'numbers': numbers, } return render(request, 'filter.html', context=context)

<p>{{ greet|cut:',' }}p>


<p>今天的日期:{{ today|date:'Y年m月d日' }}p>


<p>天气:{{ weather|default:'今天天气暂无,等待祭司预测' }}p>


<div>{{ html|safe }}div>



<div>{{ value|truncatechars:3 }}div>


<p>数字加2的结果:{{ number|add:2 }}p>


<p>列表项数量:{{ items|length }}p>


<p>首字母大写:{{ text|capfirst }}p>


<p>全部小写:{{ text|lower }}p>


<p>全部大写:{{ text|upper }}p>


<p>Slugified 文本:{{ text|slugify }}p>


<p>前三个水果:{{ items|slice:":3"|join:", " }}p>
<p>前五个字符:{{ text|slice:":5" }}p>


<p>水果列表(用逗号分隔):{{ items|join:", " }}p>


<p>随机水果:{{ items|random }}p>


<p>转义后的HTML:{{ html|escape }}p>


<p>带换行的文本:<pre>{{ "line1\nline2"|linebreaks }}pre>p>


<p>去除HTML标签后的文本:{{ html|striptags }}p>

你可能感兴趣的:(Django,python,django,笔记)