Django的模版系统

 

一丶MTV和MVC

MTV和MVC是一种软件架构,实现功能一样

MTV:在Django框架中使用

Model(模型):负责业务对象与数据库的对象(ORM)

Template(模版):负责如何把页面展示给用户

View(视图):负责业务逻辑,并在适当的时候调用Model和Template

此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

MVC:软件开发规范

MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。

M: model 模型 操作数据库

V: view 视图 展示页面 HTML

C: controller 控制器 调度 业务逻辑

二丶常用语法

在Django框架模板中存在两种特殊的标记:

{{ 变量 }} : 表示获取变量的值

{% 逻辑 %} : 表示逻辑相关操作

 

变量:

{{ 变量 }},由字母和下划线组成.

. (点) 在模版语言中有特殊的意义,可获取对象的属性值,也可调用对象的方法.

# 
def index(request):
   res = {
       # 传数字
       'num': 123,

       # 传字符串
       'string1': '中文字符',
       'string2': 'abcd',

       # 传列表
       'lis': ['熊大', '熊二', '熊三'],

       # 传字典
       'dic': {'name': '张哥', 'age': 33},

       # 传对象
       'p1': Person('Pig', 32)
  }
   return render(request, 'index.html', res)


# html页面
<h1>使用 {&nbsp;{变量}&nbsp;} 展示数据</h1>

   <p>{{ num }}</p>

   <p>{{ string1 }}</p>

   <p>{{ string2 }}</p>
  # <!--支持.的形式根据索引进行取值-->
   <p>{{ string2.0 }}</p>

   <p>{{ lis }}</p>
  # <!-- 列表也支持.的形式根据索引进行取值 -->
   <p>{{ lis.1 }}</p>

  # <!--支持字典的所有方法,不需要加(),也支持.的形式取键对应的值-->
   <p>{{ dic }}</p>
   <p>{{ dic.name }}</p>
   <p>{{ dic.keys }}</p>
   <p>{{ dic.values }}</p>


  # <!--对象单独的是内存地址,-->
   <p>{{ p1 }}</p>
  # <!--对象的属性-->
   <p>{{ p1.name }}</p>
   <p>{{ p1.age }}</p>

  # <!--对象的方法,不需要加()-->
   <p>{{ p1.talk }}</p>

  # <!--若变量不存在,不会报错,得到是一个空的字符串.-->
   <p>{{ xxx }}</p>

#PS:
当模板系统遇到一个(.)时,会按照如下的顺序去查询:
           1.在字典中查询
           2.属性或者方法
           3.数字索引
  {# .操作只能调用不带参数的方法 #}
  {{ person_list.0.dream }}

Filter过滤器:

Django提供过滤器,对展示的字符串进一步筛选

语法: {{ value|filter_name:参数 }}

注意: ':'左右没有空格,出现空格就报错

### default 默认
# 语法:{{ value|default:"nothing"}}
# value的值没有传递,或者为空类型/None时,都会调用default默认值
# 一旦settings配置文件设置了:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:'找不到',可以替代default的的作用.  
   # ps:调用string_if_invalid的优先级高于default,如果设置的变量不存在,调用string_if_invalid对应的值
   <p>
      {{ xxx|default:'aaa' }}
   </p>
### filesizeformat 格式化数据大小(例如 '13 KB', '4.1 MB', '102 bytes',最大到PB)
# 语法:{{ value|filesizeformat }}
  <p>
          {{ 1024|filesizeformat }} #1.0 KB
       </p>

       
       

### add 给变量做 +法,也具有拼接效果. 字符串拼接数字,列表拼接列表
# 语法:{{ value|add:"2" }}
  <p>
          {{ num|add:"2" }}  # num=10 加2--->12
       </p>
       <p>
          {{ lis|add:lis}}  #列表拼接
       </p>
       <p>
          {{ string1|add:'123456'}}  # 字符串拼接数字
       </p>
   
   
   
###   lower 大写
# 语法:{{ value|lower }}
       <p>
          {{ string2|lower }}
       </p>    

       
       
###   upper 大写
# 语法: {{ value|upper}}
       <p>
          {{ string2|upper }}
       </p>      

       
       
### title 标题,首字母大写
# 语法:{{ value|title }}
       <p>
          {{ string2|title }}
       </p>      

       
       
### ljust 左对齐, rjust 右对齐 ,center 居中
#语法:
  "{{ value|ljust:"10" }}"
       "{{ value|rjust:"10" }}"
       "{{ value|center:"15" }}"
       
          <p>
               "{{ string1|ljust:"10" }}"
               <br>
               "{{ string1|rjust:"10" }}"
               <br>
               "{{ string1|center:"1" }}"
           </p>    
 


### length 获取数据的长度
# 语法: {{ value|length }}
  <P>
          {{ string1|length }}
       </P>
       
       
       
###   slice 切片 , 支持正向 也支持反向
# 语法:{{value|slice:"2:-1"}}
       <p>
          {{ lis }}
          {{ lis|slice:'0:2' }}  # 切除来两个
          {{ lis|slice:'-1::-1' }}  # 反向切出来所有
       </p>

       
### first 取第一个元素
# 语法: {{ value|first }}
       <p>
          {{ string1 }}
          {{ string1|first }} # 取第一个元素
       </p>    
   
   
### last 取最后一个元素
# 语法: {{ value|last }}
       <p>
          {{ string1 }}
          {{ string1|last }} # 取第一个元素
       </p>  
       
       
### join 字符串拼接列表
# 语法: {{ value|join:" // " }}
   <p>
      {{ lis|join:'^^' }}
   </p>
   
   
### truncatechars 字符串字符多于指定的字符数量,会被截断。截断的字符串将以省略号(“...”)结尾.
# 参数:截断的字符个数
# 语法:{{ value|truncatechars:9}}
   <p>
      {{ '难念的经爱上空间的撒谎加括号大数据库很快就打'|truncatechars:10 }} # 字符分隔
   </p>
   <p>
      {{ '难念的 经爱上 空间的 撒谎加括 号大数据库很快就打'|truncatewords:3 }} #空格分隔,
   </p>
### date 日期格式化
# 语法: {{ value|date:"Y-m-d H:i:s"}}
       <p>
          {{ now|date:'Y-m-d H:i:s' }}  # 2019-08-28 15:45:50
       </p>
   
# 当在settings配置文件设置以下参数时,就会更改默认时间显示的格式.就可以达到和date一样的效果
       USE_L10N = False
       DATETIME_FORMAT = 'Y-m-d H:i:s'
       <p>
          {{ now }}
       </p>    
### safe  告诉django不需要转义
# 文字叙述:👇
   Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。
   
   # 语法:{{ value|safe }}
       'jjss':'<script> for (var i=0 ;i<5;i++){alert("123")}</script>'
  {{ jjss|safe }} # 告诉浏览器这是安全的代码
  {{ jjss }} # Django这个代码当做字符串处理 <script> for (var i=0 ;i<5;i++){alert("123")}</script>
       
   # 或者使用mark_save()方法
   from django.utils.safestring import mark_safe
   'jjss':mark_safe('<script> for (var i=0 ;i<5;i++){alert("123")}</script>')

 

自定义过滤器:

1.在app目录下创建一个名为:templatetags的包

tu

2.自定义函数

# -*-coding:utf-8-*-
# Author:Ds
from django import template  #  
register=template.Library() # 注册 , 名字必须是register


@register.filter  # 装饰器.这个函数编程一个过滤函数
def my_upper(value,arg=None):
   return value.upper()


@register.filter
def my_sum(value,arg=None):
   print(value,type(value))
   if type(value)==str:
       value=value+str(arg)
   elif type(value)==int:
       value=int(value)+arg
   return value

@register.filter(name="addSB") # name属性代表重新命名
def add_sb(value):
   return "{} SB".format(value)

 

3.在模版页面使用

#### 使用流程
  #    {# 先导入我们自定义filter那个文件 #}
  #   {% load app01_filters %}

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

# 具体如下:下
<h1>自定义过滤器</h1>
<!--加载myTags py文件-->
{% load myTags %}

{{ string2|my_upper }}

<!-- 加法 -->
{{ num|my_sum:2 }}
<!-- 减法 -->

{{ num|my_subtraction:2 }}
<!-- 乘法 -->

{{ num|my_multiplication:2 }}
<!-- 除法 -->

{{ num|my_division:2 }}

 

模版中的逻辑语法

模版语言中的for的使用

# for语法: 
{% for el in el_list %}
{{el}}
{% endfor %}

# for的一些参数
  forloop.counter 当前循环的索引值(从1开始)
  forloop.counter0 当前循环的索引值(从0开始)
  forloop.revcounter 当前循环的倒序索引值(到1结束)
  forloop.revcounter0 当前循环的倒序索引值(到0结束)
  forloop.first 当前循环是不是第一次循环(布尔值)
  forloop.last 当前循环是不是最后一次循环(布尔值)
  forloop.parentloop 本层循环的外层循环

for ... empty

# for ... empty 语法: 
{% for el in el_list %}
	{{el}}
{% empty %}   # 当循环的东西不存在或者为空时,显示empty的内容
	<li>显示为空</li>	 
{% endfor %}

if ... elif ... else

# 语法:
{% if user_list %}
  用户人数:{{ user_list|length }}
{% elif black_list %}
  黑名单数:{{ black_list|length }}
{% else %}
  没有用户
{% endif %}
#PS :
	在模板中支持的语法有:and 、or、==、>、<、!=、<=、>=、in、not in、is、is not
     
    不支持连续判断: if a>b>c   ### 不支持 
    不支持算术运算: if 1+2==3  ### 不支持   

with 给变量起名字

{% with al=123  %}  # 可以直接写一个式子
    {{ al }}
{% endwith %}


{% with al=p1.name  %}  # 也可以给复杂的变量重 新的简单变量
    {{ al }}
{% endwith %}

 

{% csrf_token %} 防止跨站请求伪造

# 防止跨站请求伪造

<form action="" method="post">
	#  name="csrfmiddlewaretoken" 
    {% csrf_token %}    # 会添加一个隐藏的input框. 当提交数据是,协同csrf令牌一同提交. 
    <input type="text" name="name">
    <button>提交</button>
</form>

 

三丶母版

即定义公共的部分

# base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书管理系统</title>

    {#  加载静态资源   #}

    {% load static %}
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/dashboard.css' %}">

    <link rel="icon" href="/static/imgs/QQ图片20190829155013.jpg">
    <style>
        .table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
            vertical-align: middle;
        }
    </style>
</head>

<body>
{#  组件  #}
{% include 'nav.html' %}

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
            <ul class="nav nav-sidebar">
                <li class="{% block pub_cls %}{% endblock %}"><a href="/publish_list/">出版社管理 </a></li>
                <li class="{% block book_cls %}{% endblock %}"><a href="/book_list/">图书管理</a></li>
                <li class="{% block aut_cls %}{% endblock %}"><a href="/author_list/">作者管理</a></li>
            </ul>
        </div>


        {% block content %}
            <h1>内容哦</h1>

        {% endblock %}
    </div>
</div>

<script src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script>
    {% block js %}

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

继承母版

子页面继承母版,减少代码的重复量

# 语法:
	{% extends 'base.html'%}

# 示例:👇
{% extends 'base.html' %}  # 继承母版
{% block aut_cls %}
    active
{% endblock %}



#PS: 在include页面定义的block不能被继承的页面进行修改block的内容的值

块(block)

子页面继承母版,可以通过block块重新写

# 语法:
	{% block 变量名%}
        #内容
    {% endblock %}
    
# 示例:👇

{% block content %}	  # 替换母版 content变量 的内容

    <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">

        <h2 class="sub-header">作者列表</h2>
        <div class="table-responsive">
            <a href="/author_add/" class="btn btn-info btn-sm">添加作者</a>
            <table class="table table-striped table-hover">
                <thead>
                <tr>
                    <th>#</th>
                    <th>序号</th>
                    <th>作者ID</th>
                    <th>作者姓名</th>
                    <th>著作</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for author in all_author %}
                    <tr>
                        <td>
                            <input type="checkbox">
                        </td>
                        <td>{{ forloop.counter }}</td>
                        <td>{{ author.pk }}</td>
                        <td>{{ author.username }}</td>
                        <td>
                            {% for book_obj in author.books.all %}
                                &nbsp;&nbsp;&nbsp;<< {{ book_obj.bname }}>>
                            {% endfor %}

                        </td>
                        <td>
                            <a class="btn btn-warning btn-sm" href="/author_edit?pk={{ author.pk }}">编辑</a>
                            <a class="btn btn-danger btn-sm" href="/author_del?pk={{ author.pk }}">删除</a>
                        </td>
                    </tr>
                {% endfor %}

                </tbody>
            </table>
                {% include 'page.html' %}

        </div>
    </div>

{% endblock %}

组件:

将一段代码单独放在页面上.

# 语法:
	{% include  'nav.html' %}
	

{% include 'nav.html' %}
{% include 'leftmenu.html' %}

静态文件:

加载静态资源,可以自动去拼接/static/路径, 当修改settings文件配置时,load static 始终获取的是你静态资源的'别名'.

### 引用静态文件      
	{% load static %}		# 自动寻找到static对应的静态资源.
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/dashboard.css' %}">



### 引用js
    {% load static %}    # 自动寻找到static对应的静态资源.
    <script src="{% static "mytest.js" %}"></script> #'/static/mytest.js'



### 多出引用同一个资源时, 可以重新命名.
    {% 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!" />  # 后续手动拼接路径

 

自定义simpletag

@register.simple_tag
def num_my(*args,**kwargs):  # 给的参数限制
    return '_'.join(args) + "*".join(kwargs.values()) #返回的值是已经处理过的.

# 页面使用
	{% load my_Tags %}  # 加载 my_Tags自定义文件
	{% num_my 'a' 'b' 'c' 'd' %}  # 参数必须加引号

 

自定义inclusion_tag

自定义include

@register.inclusion_tag('page.html')  # 必须指定一个页面
def page(num):		# 参数不限制
    '''
    num 是页数
    :param num:
    :return:
    '''
    return {'num':range(1,num+1)} # 必须是返回一个字典. 这个字典的参数还是传到page.html页面中使用
    
### 页面使用    
    {% load my_Tags %}  # 加载 my_Tags自定义文件
    {% page 10 %}   # 也会将页面加载出来

inclusion_tag面试题

### 面试题:  
	模板中使用{% sqr_list 3 %},生成如下的dropdown list 控件(下拉菜单)
    key    text
    1        1的平方是1
    2        2的平方是4
    3        3的平方是9

    请写出sqr_list的实现
 
##### my_Tags
    from django import template
    register=template.Library() # 注册
    @register.inclusion_tag('homework.html')
    def sqr_list_DEMO(num):
        data=[f'{i} ---{i}的平方是{i**2}' for i in range(1,num+1)]
        return  {'data':data}
    
####  homework.html 页面
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        {% load static %}
        <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
    </head>
    <body>
    <div class="dropdown">
    <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown"
            aria-haspopup="true" aria-expanded="true">
        Dropdown
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
        {% for foo in data %}
            <li><a href="#">{{ foo }}</a></li>
        {% endfor %}
    </ul>
    </div>
    </body>
    <script src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    </html>
    
### 展示页面
	{% load myTags %}  # 加载 mytag文件
	{% sqr_list_DEMO 10 %}  # 执行 sqr_list_DEMO 

 

 

 

 

posted on 2020-03-02 12:08  向往1  阅读(217)  评论(0编辑  收藏  举报

导航

……