Flask 系列之 SQLAlchemy

发布时间:2019-05-22 22:05:47编辑:auto阅读(2049)

    SQLAlchemy 是一种 ORM 框架,通过使用它,可以大大简化我们对数据库的操作,不用再写各种复杂的 sql语句 了。

    说明

    • 操作系统:Windows 10
    • Python 版本:3.7x
    • 虚拟环境管理器:virtualenv
    • 代码编辑器:VS Code

    实验目标

    实现网站与 mysql 数据库的连接和 CRUD 操作。

    MYSQL 的安装与配置

    打开 Ubuntu 16.04 的 bash 界面,执行下述操作

    # 安装
    sudo apt update && sudo apt install mysql-server mysql-client
    sudo service mysql status
    
    # 配置安全性
    sudo mysql_secure_installation
    sudo mysqladmin -p -u root version
    
    # 查看状态
    sudo service mysql status
    sudo service mysql start
    sudo service mysql stop
    
    # 设置字符编码
    sudo vim /etc/mysql/conf.d/mysql.cnf
    
    # 修改如下:
    [mysql]
    no-auto-rehash
    default-character-set=utf8
    [mysqld]
    socket = /var/run/mysqld.sock
    port =3306
    character-set-server=utf8  # 必须设置,否则会导致无法插入中文数据
    
    # 重启服务
    sudo service mysql restart

    mysql 常用用法

    # 进入 mysql
    mysql -u root -p
    
    # 查看当前字符编码
    show variables like 'character%';
    
    # 创建数据库 db_name
    create database db_name charset=utf8;
    
    # 显示以存在的所有数据库
    show databases;
    
    # 指定数据库 db_name
    use db_name;
    
    # 创建数据库表
    create table table_name;
    
    # 查看表信息
    desc tablename;
    
    # 删除 数据库 db_name
    drop database db_name;
    
    # 退出
    exit;

    使用 SQLAlchemy

    首先进入 mysql 的控制台界面,创建我们需要使用的数据库

    sudo mysql -u root -p
    create database todo;
    use todo;

    安装 flask-sqlalchemy

    pip install pymysql
    pip install flask-sqlalchemy

    todolist 目录下创建 config.py 文件,示例代码如下所示:

    import os
    
    basedir = os.path.abspath(os.path.dirname(__file__))
    
    
    class Config(object):
        SQLALCHEMY_DATABASE_URI = os.environ.get(
            'SQLALCHEMY_DATABASE_URI') or 'mysql+pymysql://root:mysql@127.0.0.1:3306/todo'
        SQLALCHEMY_TRACK_MODIFICATIONS = False

    修改 todolist\app\__init__.py,示例代码如下所示:

    from flask import Flask, render_template
    from flask_sqlalchemy import SQLAlchemy
    from config import Config
    
    app = Flask(__name__)
    app.config.from_object(Config)
    db = SQLAlchemy(app)
    
    
    @app.route('/')
    @app.route('/index')
    def index():
        title = 'Home'
        greet = 'Hello World'
        return render_template('index.html', title=title, greet=greet)

    todolist 目录下创建 models.py 文件,示例代码如下所示:

    from app import db
    from datetime import datetime
    
    
    class User(db.Model):
        __tablename__ = 'users'
        # __table_args__ = {"useexisting": True}
    
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(20), nullable=False, unique=True)
        email = db.Column(db.String(120), nullable=False, unique=True)
        pwd = db.Column(db.String(120), nullable=False)
    
        things = db.relationship('Thing', backref='User', lazy='dynamic')
    
        def __repr__(self):
            return "<User %r>" % self.name
    
    
    class Thing(db.Model):
        __tablename__ = 'things'
        # __table_args__ = {"useexisting": True}
    
        id = db.Column(db.Integer, primary_key=True)
        user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
        title = db.Column(db.String(20), nullable=False)
        text = db.Column(db.Text, nullable=False)
        add_date = db.Column(db.DateTime, default=datetime.now)
    
        def __repr__(self):
            return "<Todo %r>" % self.id

    修改 todolist\manage.py,示例代码如下所示:

    from app import app, db
    from models import User, Thing
    from werkzeug.security import generate_password_hash
    
    if __name__ == "__main__":
        db.drop_all()
        db.create_all()
    
        pwd = generate_password_hash('123456789')
        u1 = User(name='admin', email='admin@outlook.com', pwd=pwd)
        db.session.add(u1)
        db.session.commit()
    
        t1 = Thing(user_id=1, title='hello world', text='welcome to my hippiedom.')
        db.session.add(t1)
        db.session.commit()
    
        u2 = User.query.get(1)
        print(u2)
    
        app.run(debug=True, host='0.0.0.0', port=5000)

    此时,执行 python manage.py,若程序无数据库相关的错误信息,则表明数据库中相应表已经创建成功,我们可以在 mysql 的 shell 窗口进行查看。

    SQLAlchemy常用操作:

        查询所有用户数据
        User.query.all()
    
        查询有多少个用户
        User.query.count()
    
        查询第1个用户
        User.query.first()
        User.query.get(1)   # 根据id查询
    
        查询id为4的用户[3种方式]
        User.query.get(4)
        User.query.filter_by(id=4).all()   # 简单查询  使用关键字实参的形式来设置字段名
        User.query.filter(User.id == 4).all()  # 复杂查询  使用恒等式等其他形式来设置条件
    
        查询名字结尾字符为g的所有用户[开始 / 包含]
        User.query.filter(User.name.endswith("g")).all()
        User.query.filter(User.name.startswith("w")).all()
        User.query.filter(User.name.contains("n")).all()
        User.query.filter(User.name.like("%n%g")).all()  模糊查询
    
        查询名字和邮箱都以li开头的所有用户[2种方式]
        User.query.filter(User.name.startswith("li"), User.email.startswith("li")).all()
    
        from sqlalchemy import and_
        User.query.filter(and_(User.name.startswith("li"), User.email.startswith("li"))).all()
    
        查询age是25 或者 `email`以`itheima.com`结尾的所有用户
        from sqlalchemy import or_
        User.query.filter(or_(User.age == 25, User.email.endswith("itheima.com"))).all()
    
        查询名字不等于wang的所有用户[2种方式]
        from sqlalchemy import not_
        User.query.filter(not_(User.name == "wang")).all()
        User.query.filter(User.name != "wang").all()
    
        查询id为[1, 3, 5, 7, 9]的用户
        User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all()
    
        所有用户先按年龄从小到大, 再按id从大到小排序, 取前5个
        User.query.order_by(User.age, User.id.desc()).limit(5).all()
    
        分页查询, 每页3个, 查询第2页的数据
        pn = User.query.paginate(2, 3)
        pn.items  获取该页的数据     pn.page   获取当前的页码     pn.pages  获取总页数

    参考

关键字