Django:母版、继承、组件、自定义标签

1.for循环应用

1.1for

Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(到1结束)
forloop.revcounter0 当前循环的倒序索引值(到0结束)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环
  • 示例:
#views.py
def temp(request):
    lst1 = ["swiming",'dumpwater',"go boating"]
    lst2 = ["basketball","football","pingpang"]
    lst3 = ["run100","run1500","run400"]
    lst_all = [lst1,lst2,lst3]
    return render(request,"temp.html",{"lst1":lst1,"lst_all":lst_all})
temp.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% for water in lst1 %}
        <p>{{ forloop.counter }}-{{ water }}</p>
    {% endfor %}

</body>
</html>
  • 显示效果

当{{forloop.counter}} 换成{{forloop}}结果就是如下:

例题:把lst_all所有信息打印

<body>
<table border="1">
    <thead>
        <tr>
            <th>项目1</th>
            <th>项目2</th>
            <th>项目3</th>
        </tr>
    </thead>
    {% for temp in lst_all %}
        <tr>
        {% for i in temp %}
             <td>{{ i }}</td>
        {% endfor %}
        </tr>
    {% endfor %}

</table>
</body>
  • 显示效果

1.2for...empty

  • 若项目所有项目为空,图下显示效果,让用户感觉好像没有加载完毕

  • 用for...empty优化

    <body>
    <table border="1">
        <thead>
            <tr>
                <th>项目1</th>
                <th>项目2</th>
                <th>项目3</th>
            </tr>
        </thead>
        {#注意此时 lst_all为空#}
        {% for temp in lst_all %}
            <tr>
            {% for i in temp %}
                 <td>{{ i }}</td>
    
            {% endfor %}
            </tr>
         {% empty %}
                <td colspan="3" style="text-align:center;">空空如也</td>
        {% endfor %}
    
    </table>
    </body>
    
  • 显示效果:

1.3 if...elif 和else

{% if 5 > 2 %}
        5大于2
    {% elif 5 == 2 %}
        5等于2
    {% else %}
        5小于2
    {% endif %}

if 语句还支持and,or,==,>,<,!=,<=,>=,in,not in,is,is not 判断

{% if 5 > 2 and 2 > 1 %}
    真
{% else %}
    假
{% endif %}
{#真#}
{% if 5 > 2 > 1 %}
    真
{% else %}
    假
{% endif %}
{#假#}

注意模板中不支持连续判断。python中支持连续判断,但模板中不支持连续判断,JavaScript也不支持连续判断,不支持算数运算

语言判断 解析 结果
python--->(10>5>1) 10>5 and 5>1 True
JavaScript--->(10>5>1) 10>5 -->True--> 1>1 --->False False
模板中--->(10>5>1) 10>5-->True--> 1>1 --->False False

1.4 with语句

  • 定义一个中间变量
{#方法1#}
{% with youyong=lst_all.0.0  %}{#注意等号左右不能有空格#}
    {{ youyong }}
{% endwith %}

{#方法2#}
{% with lst_all.0.0 as youyong  %}
    {{ youyong }}
{% endwith %}

{#swiming#}

1.5 Django模板语言中属性的优先级大于方法

#定义一个字典d有属性items值为100,本身字典d有items方法,传入templates层。
def temp(request):
    d = {"a":1,"items":"100"}
    return render(request,"temp.html",{"data":d})

html前端:

{{ data.items }}
{#100#}
  • 结果为100 ,可以证明模板语言中属性的优先级大于方法

2.Csrf_token

  • 用于跨站请求伪造保护
  • 在页面的form表单里面写上{%csrf_token%}

同时也可以把:中间件MIDDLEWARE 里面内容 django.middleware.csrf.CsrfViewMiddleware,取消掉注释了

3.母版

3.1母版

  • 为什么用母版,母版可以把公用部分HTML提取出来放到公用base.html文件,便于维护和使用。

  • 在base.html中,通过定义block,把每个页面不同部分区分出来。

  • 在具体页面中先继承母版

  • 然后block名去指定替换母版中相应位置。

  • 母版:一个普通HTML提取多个页面的公共部分,定义block快

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  {% block page-css %}
  
  {% endblock %}
</head>
<body>

<h1>这是母板的标题</h1>

{% block page-main %}

{% endblock %}
<h1>母板底部内容</h1>
{% block 块名称 %}

{% endblock %}
</body>
</html>


3.2块

  • 语法: {{% block xxxx %}}

  • 通过在母板中使用{% block xxx %}来定义"块"。

    在子页面中通过定义母板中的block名来对应替换母板中相应的内容。

3.3继承

  • 语法:{% extends "base.html "%}

  • 重写block块 ----->写子页面独特的内容

  • 注意

  1. {% extends 'base.html' %} 写在第一行 前面不要有内容 有内容会显示
  2. {% extends 'base.html' %} 'base.html' 加上引号 不然当做变量去查找
  3. 把要显示的内容写在block块中
  4. 定义多个block块,定义 css js 块
  • 母版内容:

  • 继承版内容

  • 子页面如何定义自己CSS样式(JS也一样)

    • 主页面设置CSS的block快

    • 子页面写入自己CSS样式

3.4组件

  • 语法:{%include "xxxxx.html"}
  • 将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

  • 在templates文件下新建nav.html

<!--导航条代码-->
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="/exit/">exit</a></li>
                <li><a href="#">Settings</a></li>
                <li><a href="#">Profile</a></li>
                <li><a href="#" style="color:red;font-size: 20px; "><strong>{{ uname }}</strong></a></li>
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="Search...">
            </form>
        </div>
    </div>
</nav>
  • 在母版语句相应位置导入导航条:

4.静态文件

  • settings文件内配置的STATIC_URL=“/static/”,在以后项目部署的时候有可能变更,当一旦改动STATIC_URL将会出错。
  • 通过用静态文件方法优化,避免路径写死了。
  • 语法:{% load static %}
  • 在母版文件中:{% load static %}

{% load static %}
    <link rel="stylesheet" href="{% static '/plugins/bootstrap-3.3.7/css/bootstrap.css' %}">
    <link rel="stylesheet" href="{% static '/css/dsb.css' %}">

{#导入static,然后放入到link的href内与css路径拼接,static从setting中找到STATIC_URL名字,然后和后面写的路径拼接。这样无论settings改变STATIC_URL为什么都不会报错#}

注意:{% load static %} 与 {% load staticfiles %} 一样,用谁都行

  • 拓展:{%get_static_prefix%}

    {#在base.html写入如下,会在html源码中显示/static/#}
    <h1>{%get_static_prefix%}</h1>
    
    
  • 由此可见,它的功能是获取settings内STATIC_URL的名字。

这样也可以用如下写法也成立:

<link rel="stylesheet" href="{%get_static_prefix%}css/dsb.css">

5.自定义标签

5.1 simpletag

  • filter最多传入2个参数,但simpletag可以传入任意参数,创建与自定义filter一样

  • 在templatetags下创建my_tags.py文件,写入方法,

    from django import template
    register = template.Library()
    
    
    @register.simple_tag
    def join_str(*args,**kwargs):
        return "{} - {}".format("*".join(args),"&".join(kwargs.values()))
    
  • 在temp.html导入方法使用

    {% load my_tags %}
    {% join_str '1' '2' k1='3' k2='4' %} {#切记等号左右不允许有空格}
    

    注意:切记等号左右不允许有空格

  • 显示效果:

5.2 inclusion_tag

  • 多用于返回html代码片段。相比组件,inclusion_tag返回代码字段是灵活的,根据你提供的参数是变化的。

  • 它与filter和simpletag不同在于它返回的是一个字典,字典作用于render一样,要把字典交给页面渲染

  • 分页功能使用

    • 首先设置page.html片段
    <nav aria-label="Page navigation">
        <ul class="pagination">
            <li>
                <a href="#" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
    
            {% for i in num %}
             <li><a href="#">{{ i }}</a></li>
            {% endfor %}
    
            <li>
                <a href="#" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        </ul>
    </nav>
    
    • 被调用:然后在templatetags下my_tags.py写函数
    @register.inclusion_tag("page.html")
    def page(num):
        return {"num":range(1,num+1)}
    

  • 调用部分:在主页面渲染

  • 关系如下:

5.3 filter,simpletag,inclusion_tag区别

  • filter:是过滤器{{}},返回值任意指定,装饰器写法不一样
  • simpletag:是标签{%%},返回值任意指定,装饰器写法不一样
  • inclusion_tag:是标签{%%}。返回值是一个字典,交给模版渲染,装饰器写法不一样

5.4 XSS攻击

XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

@register.filter
def foo(vaules):
    a = """
    <script>
        for (var i=0;i<10;i++) {
            alert('你中毒了')
        }
    </script>
    """
    return a

原文地址:https://www.cnblogs.com/xujunkai/p/11847020.html