02-Flask之模板&模型

一、模板

  • 模板概念
- 模板是呈现给用户的界面

- 在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
项目拆分

规划项目结构
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352