Loading

Flask 系列之 SQLAlchemy

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  获取总页数

常用 API 参考

# 基本使用
db.drop_all()
db.create_all()
db.session.add(对象)
db.session.commit()

# 数据类型
db.Integer:整型
db.String (size):字符串,size 为最大长度,比如 db.String(20)
db.Text:长文本
db.DateTime:时间日期,Python datetime 对象
db.Float:浮点数
db.Boolean:布尔值

# 过滤方法
格式:<模型类>.query.<过滤方法(可选)>.<查询方法>
filter():使用指定的规则过滤记录,返回新产生的查询对象
filter_by():使用指定规则过滤记录(以关键字表达式的形式),返回新产生的查询对象
order_by():根据指定条件对记录进行排序,返回新产生的查询对象
group_by():根据指定条件对记录进行分组,返回新产生的查询对象

# 查询方法
all():返回包含所有查询记录的列表
first():返回查询的第一条记录,如果未找到,则返回None
get(id):传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回None
count():返回查询结果的数量
first_or_404():返回查询的第一条记录,如果未找到,则返回404错误响应
get_or_404(id):传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回404错误响应
paginate():返回一个Pagination对象,可以对记录进行分页处理

参考

posted @ 2019-03-26 20:57  hippieZhou  阅读(1160)  评论(0编辑  收藏  举报