from flask import Flask,render_template
app = Flask(__name__)
@app.route('/about/')
def about():
return render_template('about.html')
当然也可以对其进行目录修改:
from flask import Flask,render_template
app = Flask(__name__,template_folder=r'temp')
@app.route('/about/')
def about():
return render_template('about.html')
<h3>{{title}}</h3>
{{ foo.bar }}
{{ foo['bar'] }} # foo是一个对象 bar是一个属性
data_list
是后端传给前端一种列表形式,[“aa”,“bb”,“cc”], {% for item in data_list %}
是对取出列表中每个内容,item为每个内容
{% for item in data_list %}
<tr>
<th scope="row">1</th>
<td>{{item}}</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
{% endfor %}
自定义类:
class User:
def __init__(self,username,email):
self.username = username
self.email = email
@app.route('/')
def hello_world():
user = User(username="知了", email="xx@qq.com")
person = {
"username": "张三",
"email": "zhangsan@qq.com"
}
return render_template("index.html", user=user, person=person)
# user 和person 对象可以转到前端页面用于展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>知了传课首页</title>
</head>
<body>
<div>{{ user.username }} / {{ user.email }}</div>
<div>{{ person['username'] }} / {{ person.username }}</div>
</body>
</html>
对于键值对形式的变量,可以 对象.属性、或者对象[‘属性’] 在前端页面进行访问。
[{'id': 2, 'username': '韩超', 'password': 'qwe123', 'mobile': '1999999999'}, {'id': 4, 'username': '胡兵', 'password': 'hubing', 'mobile': '222'}]
{% for item in data_list %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.username }}</td>
<td>{{ item.password }}</td>
<td>{{ item["mobile"] }}</td>
</tr>
{% endfor %}
如果是列表套字典这种形式, {% for item in data_list %}
中的每一个item都是字典, item.属性获取对应的值。
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/about/')
def about():
context={
"hobby":"pingpang",
"name":"hb",
"age":20
}
return render_template('about.html',**context)
有一个if就有一个endif,这里的语法类似javaweb中的JSTL表达式。
{% if age>18 %}
<div>您已经满18岁,可以进入网吧!</div>
{% endif %}
@app.route("/control")
def control_statement():
age = 18
books = [{
"name": "三国演义",
"author": "罗贯中"
},{
"name": "水浒传",
"author": "施耐庵"
},]
return render_template("control.html", age=age, books=books)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>控制语句Demo</title>
</head>
<body>
{% if age>18 %}
<div>您已经满18岁,可以进入网吧!</div>
{% elif age==18 %}
<div>您刚满18岁,需要父母陪同才能进入!</div>
{% else %}
<div>您未满18岁,不能进入网吧!</div>
{% endif %}
{% for book in books %}
<div>图书名称:{{ book.name }},图书作者:{{ book.author }}</div>
{% endfor %}
</body>
</html>
? 变量可以通过 过滤器 修改, {value|过滤器},可以使用jinja2中自带的过滤器,也可以自己定义过滤器,过滤器相当于Linux下的管道符。
{{ name|striptags|title }} # 会移除 name 中的所有 HTML 标签并且改写 为标题样式的大小写格
数量:
{{ post.comments.all()|length }}
{{ question.answers|length }}
{{ post.comments.count() }}
在html里面也可以做过滤查询:
{% for comment in post.comments.filter_by(is_active=True).all() %}
<div class="comment-group">
<h3>评论列表</h3>
<ul class="comment-list-group">
{% for comment in post.comments.filter_by(is_active=True) %}
<li>
<div class="comment-content">
<p class="author-info">
<span>{{ comment.author.username }}</span>
<span>{{ comment.create_time }}</span>
</p>
<p class="comment-txt">
{{ comment.content }}
</p>
</div>
</li>
{% endfor %}
</ul>
</div>
默认值:
{{ user.signature or '' }}
这段代码使用了 or
运算符来提供一个默认值。如果 user.signature
不存在或为空,那么 user.signature or ''
的结果就是空字符串 ''
。
如果我们不想对数据进行直接渲染,进行一些操作在进行展示,我们可以自己定义一个函数,然后再前端调用.
# 自定义函数 value就是我们进行操作的值
def datetime_format(value, format="%Y年%m月%d日 %H:%M"):
return value.strftime(format)
# 将datetime_format 命名为dformat 可以直接在前端调用
app.add_template_filter(datetime_format,"dformat")
@app.route("/filter")
def filter_demo():
user = User(username="知了xxxx", email="xx@qq.com")
mytime = datetime.now()
return render_template("filter.html", user=user, mytime=mytime)
对象| 方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>过滤器使用demo</title>
</head>
<body>
<div>{{ user.username }}-{{ user.username|length }}</div>
<div>{{ mytime|dformat }}</div>
</body>
</html>
{{ user.username|length }}
可以理解为内置属性,{{ mytime|dformat }}
可以理解为对mytime执行dformat(自定义函数)。
少量转义:
{{ '{{' }}
大量转义:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
放在一个 {% raw %}
和 {% endraw %}
块内部,可以不进行填充。
使用safe对其表示不要转义:
{{ post.content|safe }}
post = db.relationship("PostModel", backref=db.backref('comments', order_by=create_time.desc(), lazy="dynamic"))
# 对当前用户的信息进行修改
g.user.username = username
g.user.signature = signature
db.session.commit()
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
? 在上面的父模板,我们使用了 {% block head %}
、{% block title %} 、 {% block content %}、{% block footer %} ,我们的子模板只需要重写一下这几个块即可.
{% extends "base.html" %} //继承
{% block title %}Index{% endblock %} //重写title块
{% block head %}
{{ super() }} //用于调用基础模板中同名块的内容
<style type="text/css"> // 这是新添加的内容
.important { color: #336699; }
</style>
{% endblock %}
{% block content %} //重写 content 块
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
//还有注意的一点是 {% block footer %} 即继承下来 因为没有重写
{% extends "base.html" %} 表示该网页继承base.html
{% block body %}
我是子模板的body
{% endblock %} #表示将内部内容填充到 父亲的{% block body %} {% endblock %} 中
@app.route("/child1")
def child1():
return render_template("child1.html")
@app.route("/child2")
def child2():
return render_template("child2.html")
这是base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">新闻</a></li>
</ul>
{% block body %}
{% endblock %}
<footer>这是底部的标签</footer>
</body>
</html>
child1.html
{% extends "base.html" %}
{% block title %}
我是子模板的标题
{% endblock %}
{% block body %}
我是子模板的body
{% endblock %}
child2.html
{% extends "base.html" %}
{% block title %}
我是child2
{% endblock %}
{% block body %}
我是child2
{% endblock %}
与ajax的结合,Ajax只是起到了一个发送请求返回数据的作用。
function refreshTitle() {
$.ajax({
type:'GET'
url: "http://127.0.0.1:5000/Title" + "?n="+ Math.random()
dataType:'json',
success: function (data) {
console.log(data);
$('#echart1_title').text(data['title'][o])
$('#echart2_title').text(data['title'][1])
$('#echart4_title').text(data['title'][2])
$('#echart5_title').text(data['title'][3])
$('#echart6_title').text(data['title'][4])
}
})
}
refreshTitle()
var processCounter =window.setInterval('refreshTitle()',360000) //当时
dataType是要求为String类型的参数,预期服务器返回的数据类型,如果不指定,JQuery将自动根据http包mime信息返回responseXML或responseText,并作为回调函数参数传递。
success:
Function类型的参数,请求成功后调用的回调函数,有两个参数
由服务器返回,并根据dataType参数进行处理后的数据。
function(data, textStatus){
//data可能是xmlDoc、jsonObj、html、text等等 this;
//调用本次ajax请求时传递的options参数
}
同步提交:当用户发送请求时,当前页面不可以使用,服务器响应页面到客户端,响应完成,用户才可以使用页面。
异步提交:当用户发送请求时,当前页面还可以继续使用,当异步请求的数据响应给页面,页面把数据显示出来 。
console.log(xhr.status);//状态码
console.log(xhr.statusText);//状态字符串
console.log(xhr.getAllResponseHeaders());//所有响应头
console.log(xhr.response);//响应体
xhr.response: 返回响应的主体数据。根据设置的responseType属性,可以是字符串、JavaScript对象、XML文档、Blob对象等。
xhr.responseText: 返回响应的主体数据作为字符串。如果设置了responseType为其他类型,则该属性为空字符串。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery 发送 AJAX 请求</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">jQuery发送AJAX请求 </h2>
<button class="btn btn-primary">GET</button>
<button class="btn btn-danger">POST</button>
<button class="btn btn-info">通用型方法ajax</button>
</div>
<script>
$('button').eq(0).click(function(){
$.get('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
console.log(data);
},'json');
});
$('button').eq(1).click(function(){
$.post('http://127.0.0.1:8000/jquery-server', {a:100, b:200}, function(data){
console.log(data);
});
});
$('button').eq(2).click(function(){
$.ajax({
//url
url: 'http://127.0.0.1:8000/jquery-server',
//参数
data: {a:100, b:200},
//请求类型
type: 'GET',
//响应体结果
dataType: 'json',
//成功的回调
success: function(data){
console.log(data);
},
//超时时间
timeout: 2000,
//失败的回调
error: function(){
console.log('出错啦!!');
},
//头信息
headers: {
c:300,
d:400
}
});
});
</script>
</body>
</html>
在Jinja2
语法中,为了减少对url
的使用,选择使用url_for()
函数来进行反转得到路由函数。
CSS
、js
继承:
@app.route('/static')
def static_demo():
return render_template("static.html")
static.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<-- 下面就是会用url_for() 函数导入相应的静态文件,比如css,js,html->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/my.js') }}"></script>
</head>
<body>
<img src="{{ url_for('static', filename='images/ironman.jpg') }}" alt="">
</body>
</html>
url_for('static', filename='js/my.js') # 相当于在static下的js/my.js 相当于路径的拼接
{% block head %}
<link rel="stylesheet" href="{{ url_for('static',filename='front/css/sign.css') }}">
{% endblock %}
from flask import Flask,url_for
app = Flask(__name__)
@app.route('/article/<id>/')
def article(id):
return '%s article detail' % id
@app.route('/')
def index(request):
print(url_for("article",id=1)) # article 为路由函数 id=1 路由函数中的参数,如果还有多的参数,会当作查询字符串拼接
return "首页"
当存在蓝图的时候,我们应该这样写:
? 用url_for生成蓝图的url,使用的格式是:蓝图名称+.+视图函数名称。比如要获取admin这个蓝图下的index视图函数的url,应该采用以下方式:
url_for('admin.index')
? 通过本文的介绍,我们深入了解了Jinja2模板引擎的核心语法和功能。从前后端参数传递到字典和数组的操作,再到流程控制过滤器、测试器和路由反转的应用,我们掌握了在开发中常用的关键技巧。同时,我们还学习了如何利用模板继承来提高代码的可维护性和可扩展性。
? Jinja2语法的灵活性和强大功能为开发者提供了广阔的可能性,无论是构建简单的网页还是复杂的应用程序,都能从中受益匪浅。希望本文对您在使用Jinja2时有所启发,并在您的开发工作中发挥积极的作用。
? 继续探索和实践Jinja2语法,您将不断发现它的魅力和实用性。祝愿您在使用Jinja2构建出令人惊艳的Web应用程序!