Django进阶-模板系统

常用语法

{{  }}和 {% %}
    变量相关的用 --> {{ ... }}
    逻辑相关的用 --> {% ... %}

变量

{{ name }}    

for循环

for...in

{% for .. in .. %}
    ...
{% endfor %}

for...in...empty

{% for .. in .. %}
    ...
{% empty %}
    ...            # 如果for循环没有数据,则执行这里的代码
{% endfor %}

遍历字典

{% for k,v in dic.items %}
    {{ k }-{{ v }}
{% endfor %}
forloop.counter        当前循环的索引值(从1开始)
forloop.counter0    当前循环的索引值(从0开始)
forloop.revcounter    当前循环的倒序索引值(从1开始)
forloop.revcounter0    当前循环的倒序索引值(从0开始)
forloop.first        当前循环是不是第一次循环(布尔值)
forloop.last        当前循环是不是最后一次循环(布尔值)
forloop.parentloop    本层循环的外层循环
for循环可用参数

if判断

Django不支持连续判断,如:a>b>c

条件支持: and 、or、==、>、<、!=、<=、>=、in、not in、is、is not

if...else

{% if 条件 %}
    ...
{% else %}
    ...
{% endif %}

if...elif...else

{% if 条件1 %}
    ...
{% elif 条件2 %}
    ...
{% else %}
    ...
{% endif %}

with声明变量

{% with name=name_lsit.2.1.1 %}
    {{ name }}
{% endwith %}

filter方法

内置的filter方法

语法:

值|方法:参数
default            如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
length            返回值的长度,作用于字符串和列表
filesizeformat    将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)
slice            切片
date            格式化
safe            可以渲染html标签, 把value当成安装的代码
truncatechars    显示指定的指定的字符数量,并且最后为 ...
truncatewords    在一定数量的字后截断字符串
cut                移除value中所有的与给出的变量相同的字符串
join            使用字符串连接列表,例如Python的str.join(list)
timesince
timeuntil
{{ value|default:"nothing"}}    # 如果value没有传值或者值为空的话就显示nothing
{{ value|length }}                # 返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
{{ value|filesizeformat }}        # 如果 value 是 123456789,输出将会是 117.7 MB。
示例

自定义的filter方法

文件路径

app01/
    __init__.py
    models.py
    templatetags/              # 在app01下面新建一个package package
        __init__.py
        app01_filters.py      # 建一个存放自定义filter的文件
    views.py

 自定义filter

from django import template
register = template.Library()


@register.filter(name="cut")
def cut(value, arg):                    # 不传参
    return value.replace(arg, "")


@register.filter(name="addSB")            # 一个参数
def add_sb(value):
    return "{} SB".format(value)
app01_filters.py
{# 先导入我们自定义filter那个文件 #}
{% load app01_filters %}

{# 使用我们自定义的filter #}
{{ somevariable|cut:"0" }}
{{ d.name|addSB }}

{# simple tag #}
{% plus "1" "2" "abc" %}
test.html

自定义simpletag

和自定义filter类似,只不过接收更灵活的参数

from django import template
register = template.Library()

@register.simple_tag(name="plus")        # 参数大于2
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)
app01_demo.py
{% load app01_demo %}

{# simple tag #}
{% plus "1" "2" "abc" %}
test.html

自定义的inclusion_tag

多用于返回html代码片段

from django import template

register = template.Library()


@register.inclusion_tag('result.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}项".format(i) for i in range(1, n+1)]
    return {"data": data}
templatetags/my_inclusion.py
<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>
templates/snippets/result.html
{% load inclusion_tag_test %}            # 加载
{% show_results 10 %}            # 调用   
templates/index.html

母版和继承

为什么要有母版

把多个页面公用部分提取出来,放在一个母版里面
其他页面只需要 继承 母版就可以了

母版里的块(占位)

{% block page-main %}
{% endblock %}

继承母版

{% extends 'base.html' %}    // 继承母版 

{% block page-main %}
    ...                        // 自定义的内容, 会取base.html里填充写好对应的块(占位好的位置)
{% endblock %}

具体使用步骤

1, 把公用的html部分提取出来,放到base.html文件中
2, 在base.html中,通过定义block,把每个页面不同的地方区别出来
3, 在具体的页面中,先继承母版
4, 通过block名去替换指定的母版中块的位置

注意事项

1, {% extends 'base.html' %} 放在子页面的第一行,base.html必须加引号
2, 可以在base.html中定义很多block,通常我们会额外定义一个page-css和page-js两个块
3, views.py 相应的函数返回对应的 子页面

组件

语法

{% include 'nav.html' %}    // 相当在本html文件里写了'nav.html'里的内容

注意事项

在继承了母版的页面引用组件, 要写在块(block)里面

静态文件

第一种方式

{% load static %}                                        # 去setting.py里面找静态文件夹的别名
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />    # 将别名与后面的路径拼接成完成的路径

或者

给静态文件起(as)一个别名

{% load static %}                        # 导入
{% static "images/hi.jpg" as myphoto %}    # 起别名
<img src="{{ myphoto }}"></img>            # 引用

第二种方式

使用get_static_prefix

{% get_static_prefix %}  --> 相当于 /static/  (动态版的别名)

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

CSRF

csrf的简单应用 

跨站伪造请求

Django中内置了一个专门处理csrf问题的中间件: django.middleware.csrf.CsrfViewMiddleware

中间件做的事情:在render返回页面的时候,在页面中塞了一个隐藏的input标签

用法

我们在html页面上的 form表单 里面 写上

{% csrf_token %}

 csrf补充

CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。

csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


class HomeView(View):

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")
方式1
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator


@method_decorator(csrf_exempt, name='dispatch')
class HomeView(View):
   
    def dispatch(self, request, *args, **kwargs):
        return super(HomeView, self).dispatch(request, *args, **kwargs)

    def get(self, request):
        return render(request, "home.html")

    def post(self, request):
        print("Home View POST method...")
        return redirect("/index/")
方式2

可以直接用在函数上

原文地址:https://www.cnblogs.com/sunch/p/9735051.html