zoukankan      html  css  js  c++  java
  • flask_sqlalchemy


    简介:

    flask_sqlalchemy 是 Flask Web 框架的一个扩展。

    使 Web 服务器以 (ORM: Object Relational Mapping) 对象关系映射的方式与数据库交互。

    一、安装 flask_sqlalchemy

    shell > pip install Flask-SQLAlchemy
    
    shell > ipython
    
    import flask_sqlalchemy
    
    print(flask_sqlalchemy.__version__)
    2.1
    
    # 如果没有报错,那就是安装成功了。

    二、配置 flask_sqlalchemy 连接数据库

    # app.py
    
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    # app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://tmp:9898@192.168.1.40/tmp_db?charset=utf8"
    # app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    db = SQLAlchemy(app)
    
    
    @app.route("/")
    def index():
        return "Hello World"
    
    if __name__ == "__main__":
        db.create_all()
        app.run(debug=True)
    
    # 上面注释掉的两行代码使用的数据库类型为 Mysql,连接数据的驱动是 PyMySQL (pip install PyMySQL)
    # 如果是 Python 2.x,那么驱动可能是 MySQLdb,而不是 PyMySQL
    
    # 启动这个 APP 的时候,会实例化一个对象 db,并且将该 app 注册到了 db 中,然后 db.create_all() 代表生成数据表 (虽然这里没有创建表)。

    三、创建表

    # app.py
    
    class User(db.Model):
        """user 用户表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(32), unique=True, nullable=False)
        address = db.Column(db.String(128))
    
        def __init__(self):
            self.name = self.address = ""
    
        def __repr__(self):
            return "<Name: %r>" % self.name
            
    # 重启服务器,然后去数据库中查看,就会多了一张名为 user 的表,且有三个字段 id, name, address
    
    # 所以说,ORM 中一张表就对应一个 Python class !

    四、增、查、更、删

    # ipython
    
    from app import db, User

    1、增

    u = User()
    u.name = "小王"
    u.address = "BJ"
    
    db.session.add(u)
    db.session.commit()
    db.session.close()
    
    # 实例化一个对象,然后给该对象的属性赋值,最后将该对象添加到数据库会话中,提交事务,关闭会话即可!
    
    # 这样就新增了一条数据到数据库中了。

    2、查

    print(User.query.all())
    
    # 查找 user 表中所有数据,注意:返回的是一个对象的列表
    
    print(User.query.first())
    
    # 查询 user 表中第一条数据,毫不意外也是个对象
    
    print(User.query.filter_by(id=1).first())
    print(User.query.filter_by(id=1, name="小王").first())
    
    # 查询 id 等于 1 的数据,只显示第一条。多个条件也是可以的。但格式只能是 key=value 的方式,多条件关系为 and。
    
    print(User.query.filter(User.id == 1).first())
    print(User.query.filter(User.id == 1, User.name == "小王").first())
    
    # 先注意一下 filter 与 filter_by 参数写法上的区别。
    # 另外再注意一下:filter 是 不 支 持 x and x 或者 x or x 这样的操作的,虽然这样写不报错...
    
    # filter 支持的操作是 > < = != 这些,当然还有上面 filter_by 的那种关系 x, y -> x and y。
    
    # 那要用这种 and、or 怎么办 ?
    
    from sqlalchemy import and_, or_
    
    print(User.query.filter(and_(User.id == 1, User.address == "BJ")).first())
    print(User.query.filter(or_(User.id == 1, User.address == "SH")).first())
    
    # 对,就这么搞
    
    print(User.query.filter_by(id=1).value("name"))
    print(list(User.query.filter_by(id=2).values("name", "address")))
    
    # 输出匹配数据的指定字段,默认是 select * form xxx,现在是 select name, address from xxx。
    # 又要注意了:.value 只能用于找到的对象是一个时,例如找到多个对象,则 .value 只返回第一个对象的值。
    
    from sqlalchemy import desc
    
    print(User.query.order_by(User.id).all())
    print(User.query.order_by(desc(User.id)).all())
    
    # 以 User.id 升序、降序排列
    
    print(User.query.limit(10).all()) == "limit 10" == "limit 0, 10"
    print(User.query.limit(10).offset(5).all()) == "limit 5, 10"
    print(User.query.slice(0, 10).all()) == "limit 0, 10"
    
    # 这不是 limit 么,从 offset 取,取 limit 条
    
    # 脑经急转弯:什么时候 0 等于 1 ?
    # 答案:limit 的时候!( limit 0, 10 其实是从第一条开始取十条 ) PS:还有 list index !

    3、更

    *
    u = User.query.filter_by(id=1).first()
    u.name = "天王"
    
    db.session.add(u)
    db.session.commit()
    db.session.close()
    
    **
    User.query.filter_by(id=2).update({"name": "地虎", "address": "SH"})
    
    db.session.commit()
    db.session.close()
    
    # 两种更新方法都在这里啦!

    4、删

    u = User.query.filter_by(id=1).first()
    
    db.session.delete(u)
    db.session.commit()
    db.session.close()
    
    # 完事!

    五、一对多

    # app.py
    
    class User(db.Model):
        """user 用户表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(32), unique=True, nullable=False)
        address = db.Column(db.String(128))
    
        def __init__(self):
            self.name = self.address = ""
    
        def __repr__(self):
            return "<Name: %r>" % self.name
    
    
    class Article(db.Model):
        """article 文章表"""
        
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        title = db.Column(db.String(64), nullable=False)
        author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
        
        def __init__(self):
            self.title = ""
            
        def __repr__(self):
            return "<Title: %r>" % self.title
    
    # 创建了两张表 user、article,且 article 表的 author_id 字段通过外键关联到了 user 表的 id 字段!
    
    # 好了,关系已经建立,标准的一对多(一个作者对应多篇文章)
    
    # ipython
    
    from app import db, User, Article
    
    print(User.query.all())
    [<Name: '小王'>, <Name: '大王'>]
    
    print(Article.query.all())
    [<Title: 'flask 学习笔记'>, <Title: '敢问路在何方'>, <Title: 'python 从入门到精通'>]
    
    # 通过上面学到的技能,新增了两个用户、三篇文章
    
    # 需求1:看看 "敢问路在何方" 的作者是谁?
    
    article = Article.query.filter_by(title="敢问路在何方").first()
    user = User.query.filter_by(id=at.author_id).first()
    
    print(user.name)
    
    # 需求2:看看 "小王" 写了哪些文章?
    
    uid = User.query.filter_by(name="小王").first()
    article_list = Article.query.filter_by(author_id=uid).all()
    
    for obj in article_list:
        print(obj.title)
    
    # 有没有更方便的方法呢 ?有
    
    # app
    
    class Article(db.Model):
        """article 文章表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        title = db.Column(db.String(64), nullable=False)
        author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    
        user = db.relationship("User", backref="articles")
    
        def __init__(self):
            self.title = ""
    
        def __repr__(self):
            return "<Title: %r>" % self.title
    
    # 只需给 Article 类加一个属性即可。注意:user 并不是一个存在的字段,而是一个属性!
    # 该属性关联到了 User 类,backref 指定反向引用的名称为 articles,即 User 表访问这个属性就可以找到该用户的所有文章!
    
    from app import db, User, Article
    
    # 需求1:
    
    article = Article.query.filter_by(title="敢问路在何方").first()
    
    print(article.user.name)
    
    # 需求2:
    
    user = User.query.filter_by(name="小王").first()
    
    for obj in user.articles:
        print(obj.title)
        
    # 方便不?只查询一张表即可!

    六、多对多

    # app.py
    
    article_tag = db.Table(
        "article_tag",
        db.Column("article_id", db.Integer, db.ForeignKey("article.id"), primary_key=True),
        db.Column("tag_id", db.Integer,db.ForeignKey("tag.id"), primary_key=True)
    )
    
    # 多对多关系需要建立一个中间表,你看建表的方式跟原来的还不一样!
    # 表名,字段,类型 需要跟外键关联的字段类型一致,外键 关联到哪张表的哪个字段,主键
    
    class Article(db.Model):
        """article 文章表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        title = db.Column(db.String(64), nullable=False)
        author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    
        user = db.relationship("User", backref="articles")
        tags = db.relationship("Tag", secondary="article_tag", backref="articles")
    
        def __init__(self):
            self.title = ""
    
        def __repr__(self):
            return "<Title: %r>" % self.title
    
    # 又加了一个属性 tags,多了一个参数 secondary 关键字指向中间表
    
    class Tag(db.Model):
        """tag 标签表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(32), unique=True, nullable=False)
    
        def __init__(self):
            self.name = ""
    
        def __repr__(self):
            return "<Name: %r>" % self.name
            
    # 多了一张 tag 表,这就是张普通表,用来存储标签信息,有个隐藏属性 articles 哦!
    
    # 多对多:一篇文章有多个标签,一个标签又能标记给多篇文章
    
    # ipython
    
    from app import db, Article, Tag
    
    t = Tag()
    t.name = "python"
    
    an = Article()
    an.title = "python 数据分析"
    an.author_id = 1
    an.tags.append(t) or an.tags.append(Tag.query.filter_by(id=1).first())
    
    db.session.add(t)
    db.session.add(an)
    db.session.commit()
    db.session.close()
    
    # 这就新加了一个标签、一篇文章,且给这篇文章加了一个标签
    
    an = Article.query.filter_by(title="python 数据分析").first()
    
    for obj in an.tags:
        print(obj.name)
    
    # 这样就查到了这篇文章的所有标签
    
    tn = Tag.query.filter_by(id=1).first()
    
    for obj in tn.articles:
        print(obj.title)
        
    # 这样就查到了这个标签的所有文章

    # End

    # 好了,这就是 flask_sqlalchemy 的连接方式、基本增、删、改、查、一对多、多对多的一些文字!全部代码如下:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    # app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://tmp:9898@192.168.1.40/tmp_db?charset=utf8"
    # app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
    
    db = SQLAlchemy(app)
    
    article_tag = db.Table(
        "article_tag",
        db.Column("article_id", db.Integer, db.ForeignKey("article.id"), primary_key=True),
        db.Column("tag_id", db.Integer,db.ForeignKey("tag.id"), primary_key=True)
    )
    
    
    class User(db.Model):
        """user 用户表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(32), unique=True, nullable=False)
        address = db.Column(db.String(128))
    
        def __init__(self):
            self.name = self.address = ""
    
        def __repr__(self):
            return "<Name: %r>" % self.name
    
    
    class Article(db.Model):
        """article 文章表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        title = db.Column(db.String(64), nullable=False)
        author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
    
        user = db.relationship("User", backref="articles")
        tags = db.relationship("Tag", secondary="article_tag", backref="articles")
    
        def __init__(self):
            self.title = ""
    
        def __repr__(self):
            return "<Title: %r>" % self.title
    
    
    class Tag(db.Model):
        """tag 标签表"""
    
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        name = db.Column(db.String(32), unique=True, nullable=False)
    
        def __init__(self):
            self.name = ""
    
        def __repr__(self):
            return "<Name: %r>" % self.name
    
    
    @app.route("/")
    def index():
        return "Hello World"
    
    if __name__ == "__main__":
        db.create_all()
        app.run(debug=True)
    View Code
  • 相关阅读:
    Hive是什么
    Hive导入数据的四种方法
    grafana安装
    ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
    linux下mysql安装报错及修改密码登录等等
    chown -R 用户名:组名 ./ 及 chown用法介绍
    Hadoop提交作业流程
    Java中常见的几种异常
    mysql索引需要了解的几个注意
    js数组依据下标删除元素
  • 原文地址:https://www.cnblogs.com/wangxiaoqiangs/p/7495973.html
Copyright © 2011-2022 走看看