• Django的模板层


    一 模版简介

    当我们通过路径访问的时候,浏览器发送请求,经过url的控制映射到对应的视图函数进行逻辑操作,需要进行响应返回数据给浏览器。

    我们之前是直接将HTML代码写在后端的Python代码里的。

    def current_datetime(request):
        now = datetime.datetime.now()
        html = "<html><body>It is now %s.</body></html>" % now   
        return HttpResponse(html)

    尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意。 让我们来看一下为什么:

    • 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。 

    • Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。

    • 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

    基于这些原因,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式,这就是我们要具体讨论的问题。

    目的是将变量(数据库的内容)如何巧妙的嵌入到html页面中(就不用之前我们用的字符串拼接了)

       python的模板:HTML代码+模板语法

    urls.py:

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^cur_time/', views.cur_time),
    ]

    views.py:这里面的render对象就是把cur_time.html这个html和数据对象cur_time进行一个杂糅渲染。把{'time':cur_time}这里面的内容替换到cur_time.html里面的{{ time }}这个里面去。替换到之后就是一个完全的html文件了。再把cur_time.html这个html文件传给前端去渲染。所以这些渲染都是在后端完成的。

    from django.shortcuts import render
    
    # Create your views here.
    import datetime
    
    def cur_time(request):
        # 获取当前时间
        cur_time = datetime.datetime.now()
        # 将数据交给前端渲染返回给浏览器
        return render(request,'cur_time.html',{'time':cur_time})     其中'cur_time.html'叫模板,template。这个{'time':cur_time}叫上下文,context。

    templates里的html文件 

    <!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>
    </head>
    <body>
    <p>当前时间{{ time }}</p>       这种html+逻辑控制语句就是模板语言!
    </body>
    </html>

    二 模版语法之变量

    1、语法:{{ 变量名 }}

    2、万能的局点号   .

    视图函数逻辑里将列表对象传到模板里,然后前端只取第3个值得写法:.索引

    views.py

    def index1(request):
        name_l = ['zrg','yj','yzz','xwj','fxc','yf']
        return render(request,'index1.html',{'names':name_l})

    templates

    <p>
        {{ names.2 }}
    </p>

    如果是字典的话传到模板,前去取值就用.键

    也可以拿属性

    三 模版之标签

    标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。

    if 标签必须跟一个endif

    {% if %}   if里面只能加一个bool值为True或者Flase的值。
    
    {% endif %}

    {% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

    {% if num > 100 or num < 0 %}
    <p>无效</p>
    {% elif num > 80 and num < 100 %}
    <p>优秀</p>
    {% else %}
    <p>凑活吧</p>
    {% endif %}

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

    for标签也必须写个endfor。

    遍历列表里每一个元素:

    {% for name in names %}
        <p>{{ name }}</p>
    {% endfor %}

    拿对应的索引与值:{{ forloop.counter }}代表索引,counter从1开始记。如果想重0开始就这么写:{{ forloop.counter0 }}

    {% for name in names %}
        <p>{{ forloop.counter }}{{ name }}</p>
    {% endfor %}

    遍历一个字典:

    {% for key,val in dic.items %}
        <p>{{ key }}:{{ val }}</p>
    {% endfor %}

    {%csfr_token%}

    在自己的页面有form表单里会发生跨站请求攻击。

    <form action="/login/" method="post">
        <input type="text" name="name">
        <input type="password" name="pwd">
        <input type="submit" name="submit">
        {% csrf_token %}
    </form>

    第一次了来{%csfr_token%}会被翻译成input标签,name属性是中间件,它的值时一堆字符串。下次form提交数据的时候把这个标签带着我就认识你了。

    <input type="hidden" name="csrfmiddlewaretoken" value="5j7Nm8CjqdMNWGdx2n48lMaBZ7hr6BXVdrk2ktEeuqeNn16M5Waqdgsq504hqig6">

    自定义标签

    固定的写法:

    1、在app下面创建一个文件夹或者包名字必须叫:templatetags

    2、写一个py文件在里面写功能,在功能的函数上方必须写一个装饰器@register.simple_tag

    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()
    
    
    @register.simple_tag
    def my_add100(v1):
        return v1 + 100

    3、在操作的html文件里面第一行去引入我们写的这个py文件

      {% load 写的py文件名 %}

    4、在html的body体里就可以用了,不需要管道符

          {{% 功能名 %}}

    注意:

      不能用于if语句

    自定义过滤器

    与自定义标签很相似@register.simple_filter

    调用方式:{{% num|过滤器名: %}}

    注意:

      最好跟一个参数,最多只能跟两个参数!

    模板的继承

    准备些两个页面:购买商品与购物车页面。

    原先两个路由,两个视图函数,两个html文件。

    公共的页面写一个母版base.html

    然后不同的地方写,相当于放了一个盒子,放什么内容取决于谁来调用这个模板,它自己去填充。

            {% block content %}
    
                
            {% endblock %}
    <!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>
        <style>
            .page-header{
                height: 90px;
                background-color: rebeccapurple;
            }
            .page-body .menu{
                height: 600px;
                background-color: antiquewhite;
                float: left;
                width: 20%;
            }
            .page-body .content{
                height: 600px;
                background-color: cornflowerblue;
                float: left;
                width: 80%;
            }
            .page-bottom{
                height: 90px;
                background-color: darkcyan;
                clear: both;
            }
        </style>
    </head>
    <body>
    <div>
        <div class="page-header"></div>
        <div class="page-body">
            <div class="menu">
                <a href="/ordered/">订单</a><br>
                <a href="/shoppingCar/">购物车</a>
            </div>
            {% block content %}
    
    
            {% endblock %}
        </div>
        <div class="page-bottom"></div>
    </div>
    </body>
    </html>
    base.html

    调用的话第一步引入母版:先加载它。必须卸载第一行

    {% extends 'base.html' %}

    第二步重新写个盒子:

            {% block content %}
    
                
            {% endblock %}

    第三步把自己的内容放到这个盒子里面。

    {% extends 'base.html' %}
    
    {% block content %}
        <div class="content">
            订单
        </div>
        
    {% endblock %}

    如果有多个盒子怎么办呢?

      只要在block后面定义不同名字即可。

     
  • 相关阅读:
    FileZilla Server下载及安装
    FileZilla Server设置虚拟目录
    FileZilla Server超详细配置
    Freaktab将于12月底关闭
    Thinkpad笔记本指点杆(小红点)自动漂移的问题
    STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)
    STC12C5A56S2和DS12C887做的电子闹铃
    联盛德 HLKW806 (九): 软件SPI和硬件SPI驱动ST7789V液晶LCD
    联盛德 HLKW806 (六): I2C驱动SSD1306 128x64 OLED液晶屏
    联盛德 HLKW806 (五): W801开发板上手报告
  • 原文地址:https://www.cnblogs.com/zhangrenguo/p/10251668.html
Copyright © 2020-2023  润新知