• Django之模板层


      在一个项目里面有一个专门放模板的文件夹Templates,有一个专门放视图的文件views,而且我们大多给浏览器响应的都应该是一个完整的页面,也就是读取的是一个HTML文件,然后再返回给浏览器。但我们在写HTML文件时,里面关于要从数据库拿数据,或者经常更改的地方又不能写死了,此时就需要用到模板语法了,在HTML文件中写上模板语法,然后在views读取HTML文件时,再对HTML文件中模板语法进行解析,替换。这样即完成解耦,又实现代码的复用性。

      一、模板语法中的变量

      Templates中的HTML文件::

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <p>{{ content }}</p>
        <p>{{ l1.0 }}</p>
        <p>{{ l1.1 }}</p>
        <p>{{ d1.name }}</p>
        <p>{{ d1.age }}</p>
        <p>{{ p1.id }}</p>
        <p>{{ p1.hobby }}</p>
      <p>{{p1.func}}</p>
    </body> </html>

      views.py文件:

    def test(request):
        l1=[1,2,4,6]
        d1={'name':'hh','age':20}
        content='你好啊,你在哪'
        class Person(object):
            def __init__(self,id,hobby):
                self.id=id
                self.hobby=hobby
         def func(self):
           return 111
    p1
    =Person('xx',30) return render(request,'test.html',{'content':content,'l1':l1,'d1':d1,'p1':p1})

      对于变量来说,我们用句点符‘.’,就可以拿到值。引用对象的方法时,拿到的是方法的返回值。

      二、模板中的过滤器

    <p>{{ value|default:'nothing' }}</p>
    默认值过滤器,当value有值时,就用它自己的值,但当value为False或空时,就用默认值‘nothing’
    <p>{{ value|length }}</p>
    返回的是值的长度,字符串、列表可以用,返回数据长度
    <p>{{ value|filesizeformat }}</p>
    返回的是一个很容易读的文件大小,比如文件为123456789字节,输出会是117.7MB
    <p>{{ value|date:'Y-m-d' }}</p>
    如果value=datetime.datetime.now(),返回的是年月日
    <p>{{ value|slice:'2:5' }}</p>
    如果value=‘qwertyu’,返回的就是erty
    <p>{{ value|truncatechars:9 }}</p>
    如果字符串长度大于截断量,就会被截断,截断的字符串将以‘...’结尾,所以实际看到的字符要少三个
    <p>{{ value|truncatewords:3 }}</p>
    这也是截断,但这是按单词数来截断
    <p>{{ value|safe }}</p>
    value=‘<a href=''>点击</a>’,如果没有safe,会把标签转义,比如‘<’转义为'&gl;',在浏览器上看到也不是‘<’,而是'&gl;',但这样破坏了我想要的形式
    但当加上safe之后,他就会原样输出

      三、模板中的标签

      1,for标签,就是遍历每一个元素

    {% for item in l1 %}
            <p>{{ item }}</p>
        {% endfor %}
    会遍历l1列表中的每一个元素,然后再放进p标签中
    {% for foo in l1 reversed %}这样就可以反向遍历了
    {% for k,v in d1.items %}
    <p>{{ k }}:{{ v }}</p>
    {% endfor %}
    这样就可以循环拿到字典中的key和value
    {% for item in l1 %}
    <p>{{ item }}</p>
    <p>{{ forloop.counter }}</p> 得到循环序号,从1开始
    <p>{{ forloop.counter0 }}</p> 得到循环序号,从0开始
    <p>{{ forloop.revcounter }}</p> 得到循环序号,比如数据长度为5,就从5开始,降序,最后一个为1
    <p>{{ forloop.revcounter0 }}</p> 得到循环序号,比如数据长度为5,就从4开始,降序,最后一个为0
    <p>{{ forloop.first }}</p> 得到第一个序号
    <p>{{ forloop.last }}</p> 得到最后一个序号
    {% endfor %}
    {% for k,v in d1.items %}
    <p>{{ k }}:{{ v }}</p>
    {% empty %}
    <p>没有这个字典,或者字典为空</p>
    {% endfor %}
    empty的作用就是,当你循环列表或字典时,没有找到或为空时,就返回empty中的内容

      2,if标签,做判断使用

    {% if num > 100 %}
            <p>大于100</p>
    {% elif num > 50 and num < 100 %} 
            <p>大于50,小于100</p>
    {% else %}
            <p>小于50</p>
    {% endif %}

      3,with标签

    {% with hobby=p1.hobby %}
            <p>{{ hobby }}</p>
        {% endwith %}
    相当于给一个复杂的东西取个别名,之后用别名就行了

      4,csrf_token,用于跨站请求伪造保护

    <form action="{% url 'log' %}" method="post">
            {% csrf_token %}
            姓名 <input type="text" name="user">
            密码 <input type="password" name="pwd">
            <input type="submit">
        </form>
    </body>
    我们之前在以post请求方式提交表单,必须在环境变量中修改设置,这是一种方法,但你这一该,以后所有的post请求都可以提交了,但我不想让所有的都可以提交,只让这一个提交咋办呢
    此时我们就不要把环境变量中修改了,只需在form表单里写上{% csrf_token %}就行了

      四、自定义标签和过滤器

      1,在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的标签和过滤器,但一般在创建app时,django会自动帮你配置,就不用自己去配置

      2,在app中创建templatetags模块(模块名只能是templatetags)

      3,创建py文件,如:my_tags.py

    from django import template
    register=template.library()
    @register.filter
    def filter_multi(v1,v2):
        return v1*v2
    @register.simple_tag
    def simple_tag_multi(v1,v2):
        return v1*v2

      4,在使用使用自定义的之前要导入创建的my_tags.py

    {% load my_tags %}

      5,使用自定义的

    {{ num|filter_multi:3 }}
    后面只能跟一个参数,可以跟上一个列表,所以在定义时,也只能定义两个参数 {
    % simple_tag_multi 2 3 %}
    可以跟上任意个参数,以空格隔开就行,所以在定义时可以定义多个参数

      五、继承

      我们在浏览网页时,会发现很多网页的大体都一样,比如电影天堂,你点进每个电影的页面时,除了没得电影的内容不一样之外,其他都一样,对于这种情况,我们是不需要每个电影都要完整的写HTML标签,可以先写一个样板,把不一样的地方,或者需要变化的地方写成block,然后在每个电影的HTML文件中再具体在block进行修改就行了,而且每个电影的HTML只需要学变化的地方就行,其他的继承样板的就行。

    样板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}
            title
        {% endblock %}</title>
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    
    <!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
    
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            .head{
                width: 100%;
                height: 50px;
                background-color: indigo;
                color: white;
                font-size: 30px;
                line-height: 50px;
            }
        </style>
    </head>
    <body>
        <div class="head">爱读书欢迎你</div>
        <div>
            <div class="left col-md-2">
                <div class="panel panel-default">
                    <div class="panel-heading">
                    <h3 class="panel-title">菜单</h3>
                    </div>
                    <div class="panel-body">
                        <p><a href="{% url 'shouye' %}">首页</a></p>
                        <p><a href="{% url 'wenxue' %}">文学</a></p>
                        <p><a href="{% url 'shige' %}">诗歌</a></p>
                        <p><a href="{% url 'xiaoshuo' %}">小说</a></p>
                    </div>
                </div>
            </div>
            <div class="right col-md-10">
            {% block content1 %}
                <div class="container">
                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th>编号</th>
                            <th>名字</th>
                            <th>价格</th>
                            <th>出版社</th>
                            <th>作者</th>
                        </tr>
                        </thead>
                        <tbody id="tbody">
                        {% block content %}
                        {% endblock %}
                        </tbody>
                    </table>
                </div>
                {% endblock %}
            </div>
        </div>
    </body>
    </html>
    View Code

    模板一:这就是一个HTML文件,交给render()就可以响应到浏览器

    {% extends 'model.html' %}     这相当于是把样板的内容复制过来,这必须写在第一句
    {% block title %}        这相当于要把样板中block title给替换掉
        诗歌
    {% endblock %}
    {% block content %}
        {% for shige in shige_list %}
            <tr>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ shige.name }}</td>
                    <td>{{ shige.price }}</td>
                    <td>{{ shige.printer }}</td>
                    <td>{{ shige.author }}</td>
                </tr>
        {% endfor %}
    {% endblock content %}   其中的content可以去掉,加上只是为了让人更加清楚看出结束是那个block

    模板二:

    {% extends 'model.html' %}
    {% block title %}
        文学
    {% endblock %}
    {% block content %}
    {% for wenxue in wenxue_list %}
        <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ wenxue.name }}</td>
                <td>{{ wenxue.price }}</td>
                <td>{{ wenxue.printer }}</td>
                <td>{{ wenxue.author }}</td>
            </tr>
    {% endfor %}
    {% endblock %}
  • 相关阅读:
    UnityWebgl错误-Uncaught DOMException: Blocked a frame with origin "" from accessing a cross-origin frame
    【Oracle123】v$sql 视图
    【QA123】ISO9126软件质量模型
    【测试工具123】HP LoadRunner
    【CSV123】如何使用Excel打开CSV并保留大数字精度
    【Java123】
    【FRM-Level2】2020 FRM二级考纲变化
    【FRM-Level2】2020 FRM二级 Current Issues
    【Oracle123】Oracle数据导入导出
    【中间件123】消息队列性能对比
  • 原文地址:https://www.cnblogs.com/12345huangchun/p/10204489.html
Copyright © 2020-2023  润新知