Django---MTV和MVC的了解,Django的模版语言变量和逻辑,常见的模板语言过滤器,自定义过滤器,CSRF了解,Django的母版(继承extends,块block,组件include,静态文件的加载load static),自定义simple_tag和inclusion_tag

Django---MTV和MVC的了解,Django的模版语言变量和逻辑,常见的模板语言过滤器,自定义过滤器,CSRF了解,Django的母版(继承extends,块block,组件include,静态文件的加载load static),自定义simple_tag和inclusion_tag

一丶MTV和MVC

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

MTV:在Django框架中使用

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

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

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

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

img

MVC:软件开发规范

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

​      M: model 模型 操作数据库

​      V: view 视图 展示页面 HTML

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

img

二丶常用语法

​   在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的包

​      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 p1.name  as al %}  # 可以as 
    {{ 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 %}

块(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 @ 2019-08-29 21:13  染指未来  阅读(320)  评论(0编辑  收藏  举报