打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Django进阶(二)

Template

之前的好多HTML文件中都包含类似“{{ }}”、“{% %}”,其实他们都是模板语言,模板本质上是HTML,但是夹杂了一些变量和标签,可以方便后端的修改前端的内容,而前端代码不用改变。

模板的组成:HTML代码+逻辑控制代码

变量:(使用双大括号来引用变量)语法格式:       {{var_name}}

实例一

新建项目:mysit,app名:blog,实现功能:后台获取当前年月日,返回给页面显示

mysit/mysit/urls.py

from django.conf.urls import url, include# 导入include模块from django.contrib import adminurlpatterns = [    url(r'^admin/', admin.site.urls),    url(r'^blog/', include("blog.urls"))  # 所有以blog开头的地址都去bolg app的urls中找对应的视图函数]

mysit/templates新建myhtml2.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>{{ year }}年{{ month }}月{{ day }}日</body></html>

mysit/blog/urls.py

from django.conf.urls import urlfrom blog import viewsurlpatterns = [    url(r'index2/$', views.myhtml2),    # 所有blog开头的网址都会找到该py 网址最后是index2则对应views.myhtml2函数]

mysit/blog/views.py

from django.shortcuts import render, HttpResponse, redirectimport datetimedef myhtml2(request):    # 获取当前年月日    year = datetime.datetime.now().year    month = datetime.datetime.now().month    day = datetime.datetime.now().day    # 方法一    #  {"year": year, "month": month, "day": day} 键对应myhtml2.html中{{}}内的参数,名称必须一样    # return render(request, "myhtml2.html", {"year": year, "month": month, "day": day})    # 方法二    #  locals()代表将该函数内的所有变量传递给myhtml2.html,变量名必须相同    return render(request, "myhtml2.html",locals())

HTML中的“{{ }}”内包含的是变量名称,所需数据由后端提供

获取属性的万能句点.

在到目前为止的例子中,我们传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象

在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

实例二

mysit/templates/myhtml2.html修改如下

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>{{ time.year }}年{{ time.month }}月{{ time.day }}日</body></html>

mysit/blog/views.py修改如下:

from django.shortcuts import render, HttpResponse, redirectimport datetimedef myhtml2(request):    # 方法一    # 获取当前时间对象,有属性.year .month .day 分别获取年月日     # HTML中获取数据  根据   {{ time.year }}年{{ time.month }}月{{ time.day}}日    # time = datetime.datetime.now()        # 方法二    # 获取当前时间对象,分别获取年月日添加到列表中    # HTML中获取数据  根据  {{ time.0 }}年{{ time.1 }}月{{ time.2}}日    # time = [ datetime.datetime.now().year,  datetime.datetime.now().month,    #          datetime.datetime.now().day]        # 方法三    # 获取当前时间对象,分别获取年月日添加到字典中    # HTML中获取数据  根据   {{ time.year }}年{{ time.month }}月{{ time.day}}日    time = {"year": datetime.datetime.now().year, "month": datetime.datetime.now().month,            "day": datetime.datetime.now().day}    return render(request, "myhtml2.html", locals())

所以在模板语言中句点(.)可以获取任意对象的任意属性

变量过滤器

# 语法格式:      {{obj|filter:param}}# value1 = "aBcDe"# HTML代码: value1|upper# 执行结果: ABCDE# value3 = 'he  llo wo r ld'# HTML代码: value3|cut:'he'# 执行结果: llo wo r ld# date 格式化日期字符串# value4 = datetime.datetime.now()# HTML代码: value4|date:'Y-m-d'# 执行结果: 2016-11-29# value5 = []# HTML代码: value5|default:'空的'# 执行结果: 空的# value6 = '<a href="#">跳转</a>'# HTML代码: value6|safe# 执行结果: 跳转# HTML代码: value6|striptags# 执行结果: 跳转# value7 = '1234'# HTML代码: value7 | filesizeformat# 执行结果: 1.2 KB# HTML代码: value7 | first# 执行结果: 1# HTML代码: value7 | length# 执行结果: 4# HTML代码: value7 | slice: ":-1"# 执行结果: 123# value8 = 'http://www.baidu.com/?a=1&b=3'# HTML代码: value8|urlencode# 执行结果: http%3A//www.baidu.com/%3Fa%3D1%26b%3D3

 

模板标签     标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)  {% tag %}

 

 

------------------------{%url   "name"   %}:引用路由配置的地址

<form action="{% url "aaa"%}" >   #代表该表单提交的数据会交给 urls.py中 别名为 “aaa” 所对应的视图函数去执行          <input type="text">          <input type="submit"value="提交">          {%csrf_token%}</form>

 

------------------------{%csrf_token%}:用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在视图函数中用的是render_to_response返回页面的方法,则该标签不会生效

其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

实例三

在实例一的基础上

mysit/templates/myhtml2.html修改如下

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><form action={% url "aaa" %} method="post"> # 在urls.py中找到别名为“aaa”所对应的函数提交数据    <input type="submit"></form></body></html>

mysit/blog/urls.py

from django.conf.urls import urlfrom blog import viewsurlpatterns = [    url(r'index2/$', views.myhtml2, name="aaa"),    # 所有blog开头的网址都会找到该py 网址最后是index2 则对应views.myhtml2函数,提交表单,因为其别名为aaa,所以提交表单时执行views.myhtml2函数]

运行,点击提交按钮你会发现以下错误

Forbidden (403)CSRF verification failed. Request aborted.HelpReason given for failure:    CSRF token missing or incorrect.    In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:    Your browser is accepting cookies.    The view function passes a request to the template's render method.    In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.    If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.    The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login.You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.You can customize this page using the CSRF_FAILURE_VIEW setting.

原因是django为了在用户提交表单时防止跨站攻击所做的保护

只需在HTML文件的表单中添加{%csrf_token%} 便可以解决问题

 

------------------------if判断{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

{% if num >= 100 %}    {% if num > 200 %}        <p>num大于200</p>    {% else %}        <p>num介于100和200之间</p>   {% endif %}{% elif num < 100 %}    <p>num小于100</p>{% else %}    <p>num等于100</p>{% endif %}{% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量{% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:{% if obj1 and obj2 or obj3 %} 

 

------------------------for循环{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

{% for obj in list %}  #代表开始执行该次循环    <li>{{ obj}}</li>{% endfor %}  #代表结束该次循环#在标签里添加reversed来反序循环列表:    {% for obj in list reversed %}    ...    {% endfor %}#{% for %}标签可以嵌套:    {% for i in list1 %}                 {% for ii in list2 %}            {{ ii }}         {% endfor %}    {% endfor %}#系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,#这个变量含有一些属性可以提供给你一些关于循环的信息1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:    {% for item in todo_list %}        {{ forloop.counter }}: {{ item }}    {% endfor %}
2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter4,forloop.revcounter0
5,forloop.first当第一次循环时值为True,在特别情况下很有用: {% for object in objects %} {% if forloop.first %}
        <li class="first">
      {% else %}
        <li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了# 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它# Django会在for标签的块中覆盖你定义的forloop变量的值# 在其他非循环的地方,你的forloop变量仍然可用#{% empty %}{{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %}#如果 li是空的可迭代对象 则执行该行代码下的内容 否不执行 <li>this is empty!</li> {% endfor %}

 

到目前为止,我们的模板范例都只是些零星的 HTML 片段,但在实际应用中,你将用 Django 模板系统来创建整个 HTML 页面。 这就带来一个常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?

解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。

本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

------------------------{%block  block_name %}     {% endblock %}

------------------------{% extends "HTML_NAME.html" %}

实例四

实现下面功能:

分别新建base.html  menu1.html  menu2.html。menu1.html  menu2.html与base.html一样,只需修改content盒子内的内容

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .head{            height: 50px;            background-color: blue;        }        .menu{            float: left;            background-color: aqua;            height: 570px;            width: 20%;        }        .content{            float: left;            height: 570px;            width: 80%;            background-color: blueviolet;        }        .footer{            height: 53px;            background-color: blue;            clear: both;        }    </style></head><body style="margin: 0"><div>    <div class = "head"></div>    <div>        <div class = "menu">        {# 根据url分发系统中的别名进行跳转#}            <a href="{% url "menu1" %}">菜单一</a><br>            <a href="{% url "menu2" %}">菜单二</a>        </div>

<div class = "content">{#menu1.html  menu2.html 在此添加不同的内容#}</div> </div> <div class = "footer"></div></div></body></html>

 

views.py代码如下

from django.shortcuts import render, HttpResponse, redirectdef base(request):    return render(request, "base.html")def menu1(request):    return render(request, "menu1.html")def menu2(request):    return render(request, "menu2.html")

 

urls.py代码如下

from django.conf.urls import urlfrom blog import viewsurlpatterns = [    url(r'^blog/base/$', views.base,name="base"),    url(r'^blog/base/menu1/$', views.menu1,name="menu1"),    url(r'^blog/base/menu2/$', views.menu2, name="menu2"),]

 

点击运行,浏览器输入网址,就会得到想要的效果,你也发现了base.html  menu1.html  menu2.html三个HTML文件有很多的重复代码,那么就让我们用{%block  block_name %}     {% endblock %}和{% extends "HTML_NAME.html" %} 来省略重复代码

base.html 修改如下

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .head{            height: 50px;            background-color: blue;        }        .menu{            float: left;            background-color: aqua;            height: 570px;            width: 20%;        }        .content{            float: left;            height: 570px;            width: 80%;            background-color: blueviolet;        }        .footer{            height: 53px;            background-color: blue;            clear: both;        }    </style></head><body style="margin: 0"><div>    <div class = "head"></div>    <div>        <div class = "menu">{#            根据url分发系统中的别名进行跳转#}            <a href="{% url "menu1" %}">菜单一</a><br>            <a href="{% url "menu2" %}">菜单二</a>        </div>{#将之前的代码(<div class = "content"> </div>)替换为下面的代码#}        {% block base %}        {% endblock %}{#base 是这个block的名字,之后的子HTML继承的时候也会标注这个名字,用来进行替换。  {% block base %}被替换的内容{% endblock %}  #}    </div>    <div class = "footer"></div></div></body></html>

 

  menu1.html  menu2.html修改如下

{% extends "base.html" %} {#上面这行代码代表继承自base.html#}{#下面这个block代码块里的内容将会代替父HTML(base.html) 里面 名为base的block代码块#}{% block base %}         <div class = "content">菜单一</div>    {% endblock %}

点击运行,浏览器输入网址,需求实现,并且比之前减少了很多代码。

 

 

 

 

 

 

 

 

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
前端教程:Django模板系统
编写你的第一个 Django 应用,第 4 部分 | Django 文档 | Django
【译】什么是 web 框架?
Django URL name详解
django中的FBV和CBV
Django~1
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服