一、模板
- 模板概念
- 模板是呈現給用戶的界面
- 在MVT中充當T的角色,實現了VT的解耦
- 模板處理分兩個過程
加載
渲染
- 模板代碼包含兩部分
靜態HTML
動態插入的代碼
- Jinja2
- Flask中使用的是Jinja2模板引擎
- Jinja2由Flask作者開發
現代化設計和友好的python模板語言
模仿Django的模板引擎
- Jinja2官方文檔
http://jinja.pocoo.org/docs/2.10/
- 優點
速度快,被廣泛使用
HTML設計和后端python分離
減少python復雜度
非常靈活、快速、安全
提供了控制,繼承等高級功能
- 模板語法
- 模板語法分兩種
變量
標簽
- 模板中的變量 {{ var }}
視圖傳遞給模板的數據
前面定義的數據
變量不存在,默認忽略
- 模板中的標簽 {% tag %}
控制邏輯
使用外部表達式
創建變量
宏定義
- 結構標簽 block
語法:
{% block xxx %}
{% endblock %}
例如:
{% block extcss %}
{% endblock %}
用途:
父模板挖坑,子模板填坑(塊操作)
- 靜態資源的加載
# 方式一: 直接寫
<link rel="stylesheet" href="/static/css/main.css">
# 方式二: 通過反向解析
<link rel="stylesheet" href={{ url_for('static',filename='css/main.css') }}>
- 結構標簽 extends
語法:
# 模板繼承
{% extends 'xxx' %}
# 繼承后需要保留塊中的內容
{{ super() }}
例如:
{% extends 'base_main.html' %}
{% block extcss %}
# 保留父模板中 extcss塊 中內容
{{ super() }}
# 新添加內容
<link rel="stylesheet" href={{ url_for('static',filename='css/index.css') }}>
{% endblock %}
用途:
模板繼承
挖坑繼承體現的是化整為零的操作
- 結構標簽 include
語法:
{% include 'xxx.html' %}
例如:
{% include 'index_content.html' %}
用途:
包含,將其他html包含進來,體現了由零到一的概念
可以將區塊代碼抽離到新文件;可以將重復小模塊抽取,反復使用。
- 宏定義 marco
語法:
{% macro fn(arg) %}
{% endmacro %}
例如(不帶參數):
# 定義
{% macro say() %}
<h3>今天高溫預警,40℃。</h3>
{% endmacro %}
# 調用
{{ say() }}
例如(帶參數):
# 定義
{% macro create_item(id,name) %}
<P>
<i>{{ id }}</i>
<span>{{ name }}</span>
</P>
{% endmacro %}
# 調用
{{ create_item(student.id,student.name) }}
例如(宏定義可導入from):
{# appmacro.html文件 #}
{% macro create_user(name) %}
<h3>用戶: {{ name }}</h3>
{% endmacro %}
{# 導入 #}
{% from 'appmacro.html' import create_user %}
{# 調用#}
{{ create_user('風吹褲襠涼颼颼') }}
用途:
宏定義,可以在模板中定義函數,在其他地方調用
備注: 可以專門創建一個頁面來寫宏定義,需要就引入即可。
- 條件控制 if
語法:
{% if 條件 %}
代碼塊
{% elif 條件 %}
代碼塊
...
{% else %}
代碼塊
{% endif %}
例如:
{% if name and name == 'admin' %}
<h1>This is admin console</h1>
{% elif name %}
<h1>Welcome {{ name }}!</h1>
{% else %}
<h1>Please login</h1>
{% endif %}
- 循環控制 for
語法:
{% for item in items %}
{{ item }}
{% endfor %}
{% for item in items %}
{{ item }}
{% else %}
# items為空時調用
{% endfor %}
例如:
{% for student in students %}
{% if loop.first %}
<p style="color: red;">{{ loop.index }}-{{ student.name }}</p>
{% endif %}
<p style="color: blue;">{{ loop.index }}-{{ student.name }}</p>
{% if loop.last %}
<p style="color: purple;">{{ loop.index }}-{{ student.name }}</p>
{% endif %}
{% else %}
<p>沒有數據了</p>
{% endfor %}
其他(loop循環信息):
loop.index 循環迭代計數(從1開始)
loop.index0 循環迭代計數(從0開始)
loop.revindex 循環迭代倒序計數(從len開始,到1結束)
loop.revindex0 循環迭代倒序計數(從len-1開始,到0結束)
loop.first 是否為循環的第一個元素
loop.last 是否為循環的最后一個元素
loop.length 循環序列中元素的個數
- 過濾器
語法:
{{ 變量 | 過濾器 | 過濾器 }}
例如:
{# 當變量未定義時,顯示默認字符串,可以縮寫為d #}
<p>{{ name | default('No name') }}</p>
{# 單詞首字母大寫 #}
<p>{{ 'hello' | capitalize }}</p>
{# 單詞全小寫 #}
<p>{{ 'XML' | lower }}</p>
{# 去除字符串前后的空白字符 #}
<p>{{ ' hello ' | trim }}</p>
{# 字符串反轉,返回"olleh" #}
<p>{{ 'hello' | reverse }}</p>
{# 格式化輸出,返回"Number is 2" #}
<p>{{ '%s is %d' | format("Number", 2) }}</p>
{# 關閉HTML自動轉義 #}
<p>{{ '<em>name</em>' | safe }}</p>
{# 四舍五入取整,返回13.0 #}
<p>{{ 12.8888 | round }}</p>
{# 向下截取到小數點后2位,返回12.88 #}
<p>{{ 12.8888 | round(2, 'floor') }}</p>
{# 絕對值,返回12 #}
<p>{{ -12 | abs }}</p>
{# 取第一個元素 #}
<p>{{ [1,2,3,4,5] | first }}</p>
{# 取最后一個元素 #}
<p>{{ [1,2,3,4,5] | last }}</p>
{# 返回列表長度,可以寫為count #}
<p>{{ [1,2,3,4,5] | length }}</p>
{# 列表求和 #}
<p>{{ [1,2,3,4,5] | sum }}</p>
{# 列表排序,默認為升序 #}
<p>{{ [3,2,1,5,4] | sort }}</p>
{# 合并為字符串,返回"1 | 2 | 3 | 4 | 5" #}
<p>{{ [1,2,3,4,5] | join(' | ') }}</p>
其他:
default 默認值
capitalize 首字母大寫
lower 全小寫
upper 全大寫
trim 去除空格
reverse 反轉
format 格式化輸出
safe 關閉轉義(已審查,沒有安全隱患)
striptags 將值中標簽去掉
round 四舍五入(截取)
abs 絕對值
first 第一個元素
last 最后一個元素
length 列表長度
sum 列表求和
sort 列表排序(升序)
join 合并字符串
二、模型基本操作
- 模型概念
- Flask默認并沒有提供任何數據庫操作API
- 我們可以選擇任何適合自己項目的數據庫來使用
- Flask數據庫操作,可以使用原生SQL語句,也可以使用ORM(SQLAlchemy,MongoEngine)
- 原生SQL缺點
代碼利用率低,條件復雜代碼語句越長,有很多相似語句;
一些SQL是在業務邏輯中拼出來的,修改需要了解業務邏輯,直接寫SQL容易忽視SQL問題;
- 對象關系映射 ORM
用于實現面向對象編程語言里不同類型系統的數據之間的轉換。
將對象的操作轉換為原生SQL。
- 易用性,可以有效減少重復SQL
- 性能損耗少
- 設計靈活,可以輕松實現復雜查詢
- 移植性好
python的ORM(SQLAlchemy)
- python中的SQLAlchemy安裝
# 其實是安裝了SQLAlchemy, flask-sqlalchemy
pip install flask-sqlalchemy
# flask-sqlalchemy 官網
http://flask-sqlalchemy.pocoo.org/2.3/
- flask-sqlalchemy初始化
- app/models.py文件中
from flask_sqlalchemy import SQLAlchemy
# 實例化對象,但還需要在__init__.py進行初始化
db = SQLAlchemy()
- app/__init.py__文件中
from app.models import db
# 數據庫連接配置(SQLite相對簡單)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sqlite3.db'
# 初始化
db.init_app(app)
啟動項目時報出警告,如果不需要可以將對應配置SQLALCHEMY_TRACK_MODIFICATIONS為False即可,以減少對象追蹤修改的系統開銷。
- 定義模型
class Student(db.Model):
# 如果想要改表名
__tablename__ = 'Worker'
s_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
s_name = db.Column(db.String(20))
s_age = db.Column(db.Integer)
flask模型中,主鍵需要自己定義,否則會報錯(每個模型對應一個表單,每個表單都需要一個主鍵)!
- 創建表單
db.create_all()
- 刪除表單
db.drop_all()
- 插入數據
stu = Student()
stu.s_name = '%d-測試' % random.randrange(10000)
stu.s_age = random.randrange(1,100)
db.session.add(stu)
db.session.commit()
- 查詢數據
# 獲取對應表單中所有數據
tudents = Student.query.all()
三、模型之數據庫
- 數據庫連接
dialect+driver://username:password@host:port/database
dialect 數據庫
driver 數據庫的驅動
username 數據庫用戶名
password 數據庫密碼
host 數據主機
port 數據庫端口號
database 連接數據庫名
SQLite數據庫連接不需要額外驅動,也不需要用戶名和密碼
- 連接數據庫指定配置
# 即上述內容
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
# 禁止對象追蹤修改
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
- 連接MySQL
- 系統中安裝有MySQL
- MySQL連接驅動
pip install pymysql
- MySQL中創建對應的數據庫
create database HelloFlask charset=utf8;
- 連接數據庫配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@localhost:3306/HelloFlask'
- 其他操作都是一樣(就是數據庫不同而已)
四、項目拆分
- 擴展的 ext.py
- 配置的 settings.py

