zoukankan      html  css  js  c++  java
  • django修身大法之美丽诱惑

    模板

    模板用于快速生成动态页面返回给客户端,模板是⼀个文本,用于分离文档的表现
    形式和内容。 模板定义了占位符以及各种用于规范文档该如何显示的模板标签。
    模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档。
    模板包含两部分:

    • html代码
    • 模板标签

    ⼀、模板位置

    • 在应用中建立templates目录,好处不需要注册,不好的地方,有多个应用的
      时候不能复用页面

    • 第⼆种是放在工程的目录下,好处是如果有多个应用,可以调用相同的页面,
      需要注册

      • 需要修改项目的配置文件settings.py
      TEMPLATES = [
          {
              'BACKEND': 'django.template.backends.django.DjangoTemplates', # 这里默认使用Django自带的模板引擎
              'DIRS': [os.path.join(BASE_DIR, 'templates')] # 模板绝对路径,如果是自己手动创建的django项目,则该内容为空,需要手动设置
              ,
              'APP_DIRS': True, # 是否在应用目录下查找模板文件
              'OPTIONS': {
                  'context_processors': [
                      'django.template.context_processors.debug',
                      'django.template.context_processors.request',
                      'django.contrib.auth.context_processors.auth',
                      'django.contrib.messages.context_processors.messages',
                  ],
              },
          },
      ]
      

      Django 模板查找机制: Django首先会查找DIRS下配置的模板路径,如果不在的话,则是在每个 app 的 templates
      文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件
      夹中找)。各个 app 的 templates 形成⼀个文件夹列表,Django 遍历这个列
      表,⼀个个文件夹进行查找,当在某⼀个文件夹找到的时候就停止,所有的都
      遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于
      Python找包)。这样设计有利当然也有弊,有利是的地方是⼀个app可以用另
      ⼀个app的模板文件,弊是有可能会找错了。所以我们使用的时候在
      templates 中建立⼀个 app 同名的文件夹,这样就好了。

    ⼆、模板的渲染

    2.1 loader加载

    好处是可以加载⼀次模板,然后进行多次渲染

    from django.template import loader #导入loader
    
    def index(request):
         temp = loader.get_template('index.html')
         # 渲染模板,生出html源码
         res = temp.render(context={'content':'hello index'})
         print(res)
         return HttpResponse(res)
    

    2.2 render

    from django.shortcuts import render
    
    render(request,templatesname,context=None)
    参数:
        request:请求对象
        templatesname:模板名称
        context:参数字典,必须是字典
    

    三、模板语法

    django模板中包括两部分:变量和内置标签。变量会在模板渲染时被其值代替,
    内置标签负责逻辑控制。

    3.1 变量

    变量在模板中的表示为:{{ 变量名 }},变量名就是render中context中的键。变量
    可以基本类型中的数值、字符串、布尔,也可以是字典、对象、列表等。django
    提供了点号来访问复杂数据结构。

    • 列表、元组的元素可以使用索引引用,不能使用负索引,语法:变量.索引
    • 字典: 字典变量.key
    • 对象: 对象.属性 对象.方法名(方法不能有参数)

    当模板系统在变量名中遇到点时,按照以下顺序尝试进行查找:

    • 字典类型查找
    • 属性查找
    • 方法调用
    • 列表类型索引

    如果模板中引用变量未传值,则会被置为空,不会报错,除非你对其进行了操作。

    3.2 过滤器

    过滤器是在变量显示之前修改它的值的⼀个方法,过滤器使用管道符。过滤器可以
    串联调用

    语法格式:

    {{ 变量|方法 }}
    

    常见的过滤器方法:

    方法名 作用 示例
    default 缺省值 {{ li|default:"缺省值"}}
    default_if_none 如果变量是none,则显示缺省值 {{ value|default_if_none:'"hello" }}
    cut 从字符中删除指定字符 {{ value|cut:" "}} 删除value中所有的空格
    length 获取字符串或列表的长度 {{ str1|length}}
    lower 将所有字母都变为⼩写 {{ value|lower}}
    upper 将所有字母都变为大写 {{ value|upper}}
    truncatechars 截取字符串前n个字符 {{ value|truncatechars:9 }}
    date 格式化日期字符串 {{ value|date:"Y-m-d H:i:s"}}
    add 增加变量的值 {{ num|add:"3"}}
    divisibleby 把变量的值除以指定值 {{ value|divisibleby:"3"}}
    first 获取列表第⼀个元素 {{ value|first }}
    last 获取列表最后⼀个元素 {{ value|last }}
    join 将列表内容链接为一个字符串 {{ value|join:'-' }}
    autoescape 设置或取消转义 {% autoescape off %}{{ data }}{%endautoescape %}
    • 自定义过滤器

      内置过滤器功能有限,如果不能满足需求,可以自己定义过滤器。

      • 在app里创建⼀个包:templatetags(名字必须是这个,且为包)

      • 在包里创建⼀个py文件

        from django import template
        # 实例化自定义过滤器注册对象
        register = template.Library()
        # name代表在模板中使用的过滤器的名称
        @register.filter(name='hello')
        def hello(value,arg):
             """
             :param value: 传给hello过滤的值
             :param arg: hello自带的参数
             :return:
             """
             return value + str(arg)
        
        @register.filter('time_ago')
            def time_ago(value):
             """
        
            定义⼀个距离当前时间多久之前的过滤器
             :param value:
             :return:
             1.如果时间间隔⼩于1分钟内,那么就显示刚刚
             2.如果时间间隔大于1分钟⼩于1⼩时,那么就显示xx分钟前
             3.如果时间间隔大于1⼩时⼩于24⼩时,那么就显示xx⼩时前
             4.如果时间间隔大于24⼩时⼩于30天,那么就显示xx天前
             5.如果时间间隔大于30天,那么就显示具体时间
             """
             if not isinstance(value, datetime.datetime):
                 return value
             now = datetime.datetime.now()
             timestamp = (now - value).total_seconds()
             if timestamp < 60:
                 return '刚刚'
             elif timestamp >= 60 and timestamp < 60 * 60:
                 return '{}分钟前'.format(int(timestamp / 60))
             elif timestamp >= 60 * 60 and timestamp < 60 * 60 * 24:
                 return '{}⼩时前'.format(timestamp / 60 / 60)
             elif timestamp >= 60 * 60 * 24 and timestamp < 60 * 60 * 23 *
            30:
                 return‘{}天前'.format(int(timestamp/68/68/24))
        	else:
         		return value.strftime('%Y-%m-%d %H:%M')
        
        
      • 在模板中使用

        {% load customfilter %} #加载自定义过滤器的模块
        <!DOCTYPE html>
        <html lang="en">
        <head>
         <meta charset="UTF-8">
         <title>Title</title>
        </head>
        <body>
        {{ name |hello:' how are you' }} #使用自定义过滤器
        </body>
        </html>
        

    3.3 内置标签

    语法:{% tag %}

    1.if标签

    {% if express1 %}
    	# to do
    {% elif express2 %}
    	# to do
    {% else %}
    	# to do
    {% endif %}
    
    • if表达式中使用以下运算符(优先级从⾼到低):
      • < >= <= == !=
      • in 、not in
      • is、is not
      • not
      • and
      • or
    • 不要在表达式中使用(),可以使用if嵌套实现功能
    • 不⽀持 if 3 < b < 5这种写法

    2.for

    遍历可迭代对象

    {% for x in y %}
    
    ...
    {% endfor %}
    
    • 反向迭代(reversed)
    {% for value in c [1,2,3,4,5] reversed %}
     <span>{{ value }}---</span>
    {% endfor %}
    
    • empty 当可迭代对象为空或不存在时执行,否则不执行
    {% for value in c %}
    	<span>{{ value }}---</span>
    {% empty %}
    	数据不存在
    {% endfor %}
    
    • 字典迭代
    # e = {'a1':20,'b1':40}
    {% for k,v in e.items %}
    <div>{{ k }}---{{ v }}</div>
    {% endfor %}
    
    • 获取for循环迭代的状态
    变量名称 变量说明
    forloop.counter 获取迭代的索引 从1开始
    forloop.counter0 获取迭代的索引 从0开始
    forloop.revcounter 迭代的索引从最大递减到1
    forloop.revcounter0 迭代的索引从最大递减到0
    forloop.first 是否为第⼀次迭代
    forloop.last 是否为最后⼀次迭代
    forloop.parentloop 获取上层的迭代对象
    {% for i in c %}
     <li>{{ forloop.first }}</li>
     <li>{{ forloop.last }}</li>
     <li>{{ forloop.counter }}</li>
     <li>{{ forloop.counter0 }}</li>
     <li>{{ forloop.revcounter }}</li>
     <li>{{ forloop.revcounter0 }}</li>
    {% endfor %}
    

    3. ifequal/ifnotequal

    用于判断两个值相等或不等的

    {% ifequal var var %}
    {% endifequal %}
    {% ifnotequal var var %}
    {% endifnotequal %}
    

    4.注释

    • 单行注释
    {# 注释内容 #}
    
    • 多行注释
    {% comment %}
    ...
    {% endcomment %}
    

    5.跨站请求伪造 csrf

    防止网站受第三方服务器的恶意攻击(确定表单到底是不是本网站的表单传递过来
    的)。csrf相当于在表达中增加了⼀个隐藏的input框,用于向服务器提交⼀个唯⼀
    的随机字符串用于服务器验证表单是否是本服务器的表单。

    使用:

    settings.py

    MIDDLEWARE = [
    'django.middleware.csrf.CsrfViewMiddleware',
    ]
    

    表单里

    <form action=
    "" method="post">
     {% csrf_token %}
    
    <input type="text" name="username">
    
    <p><input type="submit"></p>
    </form>
    
    • 全站禁用csrf
    #在settings中设置
    MIDDLEWARE = [
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     #'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    • 局部禁用csrf
    #在不想检验csrf的视图函数前添加装饰器@csrf_exempt。
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    
    @csrf_exempt
    def csrf1(request):
     pass
    
    • ajax验证csrf
    Ajax提交数据时候,携带CSRF:
    a. 放置在data中携带
    <form method="POST" action="/csrf1.html">
     {% csrf_token %}
     <input id="username" type="text" name="username" />
     <input type="submit" value="提交"/>
     <a onclick="submitForm();">Ajax提交</a>
    </form>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
     function submitForm(){
     var csrf = $('input[name="csrfmiddlewaretoken"]').val();
     var user = $('#user').val();
     $.ajax({
     url: '/csrf1.html',
     type: 'POST',
     data: { "user":user,'csrfmiddlewaretoken': csrf},
     success:function(arg){
     console.log(arg);
     }
     })
     }
    </script>千
    

    注意:

    csrf的意义在于 给每⼀个表单都设置⼀个唯⼀的csrf的值 并且cookie也存储⼀份
    当提交表单过来的时候 判断cookie中的值 和csrf_token中的值 是否都为本网站生
    成的 如果验证通过则提交 否则 403

    6.模板导入标签( include)

    可以把指定html文件代码导入到当前文件,实现模板代码的复用/重用。语法格
    式:

    {% include '路径/xxx.html' %}
    

    7.url标签

    在模板中url标签可用于反向解析

    <h2><a href="{% url 'App:index' %}">动态生成路由地址不带参的跳转</a>
    </h2>
    <h2><a href="{% url 'App:args1' 1 2 %}">动态生成路由地址带参的跳转</a>
    </h2>
    <h2><a href="{% url 'App:args1' num1=1 num2=2 %}">动态生成路由地址带关
    键字参数的跳转</a></h2>
    

    四、模板继承

    在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代
    码?Django 解决此类问题的首选方法是使用⼀种优雅的策略—— 模板继承 。
    本质上来说,模板继承就是先构造⼀个基础框架模板,而后在其子模板中对它所包
    含站点公用部分和定义块进行重载。

    • {% extends %} 继承父模板
    • {% block %} 子模板可以重载这部分内容。
    • {{ block.super }}调用父模板的代码

    使用继承的⼀种常见方式是下面的三层法:

    • 创建base.html模板,在其中定义站点的主要外观感受。这些都是不常修改甚
      ⾄从不修改的部分。
    • 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。这些模板拓展
      相应的区域模板。
    • 自己的页面继承自模板,覆盖父模板中指定block

    注意事项:

    • 如果在模板中使用 {% extends %} ,必须保证其为模板中的第⼀个模板标记。
      否则,模板继承将不起作 用。
    • ⼀般来说,基础模板中的 {% block %} 标签越多越好。
    • 如果发觉自己在多个模板之间有重复代码,你应该考虑将该代码放置到父模板
      的某个 {% block %} 中。
    • 不在同⼀个模板中定义多个同名的 {% block %} 。
    • 多数情况下, {% extends %} 的参数应该是字符,但是如果直到运行时方能确
      定父模板名称,这个参数也 可以是个变量。

    五、静态资源配置

    什么是静态资源:css、js、images 需要从外部导入的资源

    5.1创建static文件夹(通常放在根目录下)

    5.2需要在settings注册

    STATIC_URL='/static/'
    
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')
    ]
    

    5.3在模板中使用静态资源

    {% load static %} #放置到模板开头
     <img src="/static/img/img.jpeg" alt=""> #硬编码
     <img src="{% static 'img/img.jpeg' %}" alt=""> #动态写法,建议用这种
    

    六、jinja2模板引擎配置

    • 安装jinja2模板引擎
    pip install jinja2
    
    • 设置jinja2环境变量
    # -*- coding: utf-8 -*-
    from jinja2 import Environment
    from django.contrib.staticfiles.storage import staticfiles_storage
    from django.urls import reverse
    
    
    def jinja2_environment(**options):
        env = Environment(**options)
        env.globals.update({
            'static': staticfiles_storage.url,
            'url': reverse,
        })
        return env
    
    • 配置(setting.py)

      • 独立使用jinja2,不使用Django模板引擎
      #独立使用jinja2
      INSTALLED_APPS = [
       #'django.contrib.admin', # 注释了admin
       .....
      ]
      #模板配置
      TEMPLATES = [{
       'BACKEND':
      'django.template.backends.jinja2.Jinja2',#jinja2模版
       'DIRS': [
       os.path.join(BASE_DIR, 'templates'),#模版文件位置
       ],
       'APP_DIRS': True,
       'OPTIONS': {
       'context_processors': [
       'django.template.context_processors.debug',
       'django.template.context_processors.request',
      
      
      'django.contrib.auth.context_processors.auth',
      
      
      'django.contrib.messages.context_processors.messages',
       ],
       'environment': 'App.jinja2_env.environment', # 配置环
      境,jinja的配置文件位置
       },
       },
       ]
      
      • 两个同时使用
      #模板配置
      TEMPLATES = [{
       'BACKEND': 'django.template.backends.jinja2.Jinja2',#jinja2模
      版
       'DIRS': [
       os.path.join(BASE_DIR, 'templates2'),#修改模版文件位置
       ],
       'APP_DIRS': True,
       'OPTIONS': {
       'context_processors': [
       'django.template.context_processors.debug',
       'django.template.context_processors.request',
       'django.contrib.auth.context_processors.auth',
      
      
      'django.contrib.messages.context_processors.messages',
       ],
       'environment': 'App.jinja2_env.environment', # 配置环
      境,jinja的配置文件位置
       },
       },
       {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [os.path.join(BASE_DIR, 'templates')]
       ,
       'APP_DIRS': True,
       'OPTIONS': {
       'context_processors': [
       'django.template.context_processors.debug',
       'django.template.context_processors.request',
       'django.contrib.auth.context_processors.auth',
      
      
      'django.contrib.messages.context_processors.messages',
       ],
       },
       },
       ]
      
      
    • 静态资源和url

    <p>
     <a href="{{ url('app:index') }}">dddd</a>
    </p>
    <img src="{{ static('images/1.jpg') }}" alt="">
    
  • 相关阅读:
    常用的公共 DNS 服务器 IP 地址
    组网参考资料
    华为交换机配置telnet、SSH
    华为三层交换+双链路出口
    ACL流策略
    MacBook苹果电脑绕过BootCamp安装Win7双系统
    nslookup
    熟悉Linux操作系统的命令接口、图形接口和程序接口
    “发现一个错误”——laravel开发
    document.forms用法示例介绍
  • 原文地址:https://www.cnblogs.com/williamweson/p/13597618.html
Copyright © 2011-2022 走看看