24. Flask 自定义模型类

自定义模型类

本篇章介绍Flask自定义模型类的概念,以及写一个快速入门的示例,基本内容如下:

  • 定义两个模型类,并创建数据库表
  • 创建数据,写入数据库
  • 编写模板以及视图函数,在页面展示数据

定义模型

模型表示程序使用的数据实体,在Flask-SQLAlchemy中,模型一般是Python类,继承自db.Model,db是SQLAlchemy类的实例,代表程序使用的数据库。

类中的属性对应数据库表中的列。id为主键,是由Flask-SQLAlchemy管理。db.Column类构造函数的第一个参数是数据库列和模型属性类型。

如下示例:定义了两个模型类,作者和书名。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import pymysql
pymysql.install_as_MySQLdb()

app = Flask(__name__)

class Config(object):
    """配置参数"""
    # 设置连接数据库的URL
    user = 'root'
    password = '*********'
    database = 'flask_ex'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@127.0.0.1:3306/%s' % (user,password,database)

    # 设置sqlalchemy自动更跟踪数据库
    SQLALCHEMY_TRACK_MODIFICATIONS = True

    # 查询时会显示原始SQL语句
    # app.config['SQLALCHEMY_ECHO'] = True

    # 禁止自动提交数据处理
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False

# 读取配置
app.config.from_object(Config)

# 创建数据库sqlalchemy工具对象
db = SQLAlchemy(app)

#定义模型类-作者
class Author(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32),unique=True)
    email = db.Column(db.String(64))
    au_book = db.relationship('Book',backref='author')
    def __str__(self):
        return 'Author:%s' %self.name

#定义模型类-书名
class Book(db.Model):
    __tablename__ = 'books'
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    leader = db.Column(db.String(32))
    au_book = db.Column(db.Integer,db.ForeignKey('author.id'))
    def __str__(self):
        return 'Book:%s,%s'%(self.info,self.lead)


if __name__ == '__main__':

    # 删除所有表
    db.drop_all()

    # 创建所有表
    db.create_all()

执行脚本之后,到mysql中查看表结构如下。

创建表 db.create_all()

mysql> show tables;
+--------------------+
| Tables_in_flask_ex |
+--------------------+
| author             |
| books              |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

查看author表结构 desc author

mysql> desc author;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(32) | YES  | UNI | NULL    |                |
| email | varchar(64) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

查看books表结构 desc books

mysql> desc books;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| info    | varchar(32) | YES  | UNI | NULL    |                |
| leader  | varchar(32) | YES  |     | NULL    |                |
| au_book | int(11)     | YES  | MUL | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

创建数据

...
if __name__ == '__main__':

    # 生成数据
    author_1 = Author(name='我吃西红柿', email='xihongshi@163.com')
    author_2 = Author(name='萧潜', email='xiaoqian@126.com')
    author_3 = Author(name='唐家三少', email='sanshao@163.com')
    book_1 = Book(info='吞噬星空', leader='罗峰')
    book_2 = Book(info='寸芒', leader='李杨')
    book_3 = Book(info='飘渺之旅', leader='李强')
    book_4 = Book(info='冰火魔厨', leader='融念冰')
    # 把数据提交给用户会话
    db.session.add_all([author_1, author_2, author_3, book_1, book_2, book_3, book_4])
    # 提交会话
    db.session.commit()

在main方法下创建多个作者以及书本的数据,执行脚本后,查看mysql数据,如下:

mysql> select * from author;
+----+-----------------+-------------------+
| id | name            | email             |
+----+-----------------+-------------------+
|  1 | 我吃西红柿      | xihongshi@163.com |
|  2 | 萧潜            | xiaoqian@126.com  |
|  3 | 唐家三少        | sanshao@163.com   |
+----+-----------------+-------------------+
3 rows in set (0.00 sec)

mysql> select * from books;
+----+--------------+-----------+---------+
| id | info         | leader    | au_book |
+----+--------------+-----------+---------+
|  1 | 吞噬星空     | 罗峰      |    NULL |
|  2 | 寸芒         | 李杨      |    NULL |
|  3 | 飘渺之旅     | 李强      |    NULL |
|  4 | 冰火魔厨     | 融念冰    |    NULL |
+----+--------------+-----------+---------+
4 rows in set (0.00 sec)

mysql> 

使用 flask_wtf 编写视图函数的表单

1.编写完整flask应用,包含视图函数

from flask import Flask,render_template,url_for,redirect,request
from flask_sqlalchemy import SQLAlchemy
import pymysql
pymysql.install_as_MySQLdb()
# 导入Flask-WTF表单
from flask_wtf import FlaskForm
# 导入表单所需要的字段类型
from wtforms import StringField, PasswordField, SubmitField
# 导入表单的验证器
from wtforms.validators import DataRequired, EqualTo
# 启动命令的管理类
from flask_script import Manager   

app = Flask(__name__)

class Config(object):
    """配置参数"""
    # 设置连接数据库的URL
    user = 'root'
    password = '*************'
    database = 'flask_ex'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@127.0.0.1:3306/%s' % (user,password,database)

    # 设置sqlalchemy自动更跟踪数据库
    SQLALCHEMY_TRACK_MODIFICATIONS = True

    # 查询时会显示原始SQL语句
    # app.config['SQLALCHEMY_ECHO'] = True

    # 禁止自动提交数据处理
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False

    # 设置密钥,用于csrf_token的加解密
    app.config["SECRET_KEY"] = "xhosd6f982yfhowefy29f"

# 读取配置
app.config.from_object(Config)

# 创建数据库sqlalchemy工具对象
db = SQLAlchemy(app)

#定义模型类-作者
class Author(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(32),unique=True)
    email = db.Column(db.String(64))
    au_book = db.relationship('Book',backref='author')
    def __str__(self):
        return 'Author:%s' %self.name


#定义模型类-书名
class Book(db.Model):
    __tablename__ = 'books'
    id = db.Column(db.Integer,primary_key=True)
    info = db.Column(db.String(32),unique=True)
    leader = db.Column(db.String(32))
    au_book = db.Column(db.Integer,db.ForeignKey('author.id'))
    def __str__(self):
        return 'Book:%s,%s'%(self.info,self.leader)


# 定义表单的模型类,用来添加书本以及作者数据
class AddAuthorBook(FlaskForm):
    """自定义的注册表单模型类"""
    # DataRequired 保证数据必须填写,并且不能为空
    author_name = StringField(label="作者名称", validators=[DataRequired("作者名称不能为空")]) #  参数:名字,验证器列表
    book_info = StringField(label="书本信息", validators=[DataRequired("书本信息不能为空")])
    submit = SubmitField(label="添加")

@app.route('/',methods=['GET','POST'])
def index():
    #查询所有作者和书名信息
    authors = Author.query.all()
    books = Book.query.all()
    #创建表单对象
    form = AddAuthorBook()
    if form.validate_on_submit():
        #获取表单输入数据
        author_name = form.author_name.data
        book_info = form.book_info.data
        #把表单数据存入模型类
        db_author = Author(name=author_name)
        db_book = Book(info=book_info)
        db_book.leader = author_name
        db_book.au_book = db_author.id
        #提交会话
        db.session.add_all([db_author,db_book])
        db.session.commit()

        #添加数据后,再次查询所有作者和书名信息
        authors = Author.query.all()
        books = Book.query.all()
        return render_template('index.html',author=authors,book=books,form=form)
    else:
        if request.method=='GET':
            render_template('index.html', author=authors, book=books,form=form)
    return render_template('index.html',author=authors,book=books,form=form)

#删除作者
@app.route('/delete_author<id>')
def delete_author(id):
    print('delete author id = %s' % id)
    #精确查询需要删除的作者id
    author = Author.query.get(id)
    db.session.delete(author)
    db.session.commit()
    #直接重定向到index视图函数
    return redirect(url_for('index'))

#删除书名
@app.route('/delete_book<id>')
def delete_book(id):
    print('delete book id = %s' % id)
    #精确查询需要删除的书名id
    book = Book.query.get(id)
    db.session.delete(book)
    db.session.commit()
    #直接重定向到index视图函数
    return redirect(url_for('index'))

if __name__ == '__main__':

    # 创建Manager管理类的对象
    manager = Manager(app)

    # 通过管理对象来启动flask
    manager.run()

2.设置index.html模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>玄幻系列</h1>
    <form method="post">
        {{ form.csrf_token }}
        <p>作者:{{ form.author_name }}</p>
        <p>书名:{{ form.book_info }}</p>
        <p>{{ form.submit }}</p>
    </form>

    <hr>

    <ul>
        {% for item in author %}
        <li>{{ item }}</li><a href='/delete_author{{ item.id }}'>删除</a>
        {% endfor %}
    </ul>

    <hr>

    <ul>
        {% for item in book %}
        <li>{{ item }}</li><a href='/delete_book{{ item.id }}'>删除</a>
        {% endfor %}
    </ul>
</body>
</html>

3.执行python3 db_demo2.py runserver启动服务后,进行功能测试

从上面的几个示例,基本清楚讲解了模型类如何定义,表单如何设置,模板中如何展示数据,表单如何提交数据,数据如何设置删除等功能。

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

推荐阅读更多精彩内容