python_flask_ORM

news/2024/7/1 22:46:56

 

ORM (Object-Relation Mapping) 对象-关系映射.

主要实现模型对象到关系数据库数据的映射.

优缺点:

  • 优点:
    • 只需要面向对象编程,不需要使用sql语言
    • 实现数据模型和数据库的解藕,及不用关心是什么数据库,更改简单配置即可更换数据库。
  • 缺点
    • 有部分性能损耗

1、flask_sqllalchemy的基本配置

  • 安装:pip install flask_sqlalchemy
    • 如果链接mysql数据库需要按张mysqldb:pip install flask_mysql
  • 基本配置
    • 配置链接数据库
      # 链接mysql数据库:mysql://用户名:密码@ip地址:端口/库
      app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
    • 其他配置
      # 动态追踪修改设置,如未设置只会提示警告
      app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
      #查询时会显示原始SQL语句
      app.config['SQLALCHEMY_ECHO'] = True
    • 配置完成后需要去mysql中创建所需的库
    • 其他配置
    • 链接其他数据库
      # Postgres
      postgresql://scott:tiger@localhost/mydatabase
      
      # Oracle
       oracle://scott:tiger@127.0.0.1:1521/sidname
      
      # SQlite(注意开头是四个"/" )
      sqlite:absolute/path/to/foo.db
  • 常用的SQLAlchemy字段类型
类型名python中类型说明
Integerint普通整数,一般是32位
SmallIntegerint取值范围小的整数,一般是16位
BigIntegerint或long不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal普通整数,一般是32位
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长Unicode字符串
UnicodeTextunicode变长Unicode字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date时间
Timedatetime.datetime日期和时间
LargeBinarystr二进制文件
  • 常用的SQLAlchemy列选项
选项名说明
primary_key如果为True,代表表的主键
unique如果为True,代表这列不允许出现重复的值
index如果为True,为这列创建索引,提高查询效率
nullable如果为True,允许有空值,如果为False,不允许有空值
default为这列定义默认值
  • 常用的SQLAlchemy关系选项
选项名说明
backref在关系的另一模型中添加反向引用
primary join明确指定两个模型之间使用的联结条件
uselist如果为False,不使用列表,而使用标量值
order_by指定关系中记录的排序方式
secondary指定多对多关系中关系表的名字
secondary join在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件
  • 配置变量 
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    
    
    app = Flask(__name__)
    
    # 设置连接数据库的URL
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/test'
    
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    # 查询时会显示原始SQL语句
    app.config['SQLALCHEMY_ECHO'] = True
    实例化链接
    db = SQLAlchemy(app)

 

  • 简单定义
class User(db.Model):
    # 定义表明(不定义用的是模型对象名的小写)
    __tablename__ = 'users'
    # 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True, index=True)
    
  • 一对多模型
    class Role(db.Model):
        #关键代码
        us = db.relationship('User', backref='role', lazy='dynamic')
    
    
    class User(db.Model):
    
        role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    
    """
    其中realtionship描述了Role和User的关系。在此文中,第一个参数为对应参照的类"User"
    第二个参数backref为类User申明新属性的方法
    第三个参数lazy决定了什么时候SQLALchemy从数据库中加载数据
    如果设置为子查询方式(subquery),则会在加载完Role对象后,就立即加载与其关联的对象,这样会让总查询数量减少,但如果返回的条目数量很多,就会比较慢
    设置为 subquery 的话,role.users 返回所有数据列表
    另外,也可以设置为动态方式(dynamic),这样关联对象会在被使用的时候再进行加载,并且在返回前进行过滤,如果返回的对象数很多,或者未来会变得很多,那最好采用这种方式
    设置为 dynamic 的话,role.users 返回查询对象,并没有
    """

     

  • 多对多模型
    tb_student_course = db.Table(
        'tb_student_course',
         db.Column('student_id', db.Integer, db.ForeignKey('students.id')),
         db.Column('course_id', db.Integer, db.ForeignKey('courses.id'))
                                 )
    
    class Student(db.Model):
        __tablename__ = "students"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
    
        courses = db.relationship('Course', secondary=tb_student_course,
                                  backref=db.backref('students', lazy='dynamic'),
                                  lazy='dynamic')
    
    class Course(db.Model):
        __tablename__ = "courses"
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
    
    
    """
    多对多通过第三方表 tb_student_course 建立链接,表内只有两个外键分别指向多对多的两个表的ID(主键)
    """

     

  • 自关联模型
    • 自关联一对多(适用于省市区三级联动,评论的父评论和子评论的关系)
      class Comment(db.Model):
          """评论"""
          __tablename__ = "comments"
      
          id = db.Column(db.Integer, primary_key=True)
          # 评论内容
          content = db.Column(db.Text, nullable=False)
          # 父评论id
          parent_id = db.Column(db.Integer, db.ForeignKey("comments.id"))
          # 父评论(也是评论模型)
          parent = db.relationship("Comment", remote_side=[id],
                                   backref=db.backref('childs', lazy='dynamic'))
      

       

    • 自关联的多对多(用户之间的关注信息)
      tb_user_follows = db.Table(
          "tb_user_follows",
          db.Column('follower_id', db.Integer, db.ForeignKey('info_user.id'), primary_key=True),  # 粉丝id
          db.Column('followed_id', db.Integer, db.ForeignKey('info_user.id'), primary_key=True)  # 被关注人的id
      )
      
      class User(db.Model):
          """用户表"""
          __tablename__ = "info_user"
      
          id = db.Column(db.Integer, primary_key=True)  
          name = db.Column(db.String(32), unique=True, nullable=False)
          # 用户所有的粉丝,添加了反向引用followed,代表用户都关注了哪些人
          followers = db.relationship('User',
                                      secondary=tb_user_follows,
                                      primaryjoin=id == tb_user_follows.c.followed_id,
                                      secondaryjoin=id == tb_user_follows.c.follower_id,
                                      backref=db.backref('followed', lazy='dynamic'),
                                      lazy='dynamic')
      
      
      """
      通过类似普通多对多的第三方表来维护自关联的多对多关系
      多对多通常使用第三方表来维护关系
      """

       

常用的SQLAlchemy查询过滤器

过滤器说明
filter()把过滤器添加到原查询上,返回一个新查询
filter_by()把等值过滤器添加到原查询上,返回一个新查询
limit使用指定的值限定原查询返回的结果
offset()偏移原查询返回的结果,返回一个新查询
order_by()根据指定条件对原查询结果进行排序,返回一个新查询
group_by()根据指定条件对原查询结果进行分组,返回一个新查询

常用的SQLAlchemy查询执行器

方法说明
all()以列表形式返回查询的所有结果
first()返回查询的第一个结果,如果未查到,返回None
first_or_404()返回查询的第一个结果,如果未查到,返回404
get()返回指定主键对应的行,如不存在,返回None
get_or_404()返回指定主键对应的行,如不存在,返回404
count()返回查询结果的数量
paginate()返回一个Paginate对象,它包含指定范围内的结果

基本操作

插入

  • # 创建模型类对象
    ro1 = Role(name='admin')
    # 执行add添加命令
    db.session.add(ro1)
    # 如果是多条数据(多个用于提交的模型类对象)可使用add_all提交列表数据
    # db.session.add_all([us1,us2,us3,us4,us5,us6,us7,us8,us9,us10])
    # 提交到数据库(未提交数据库不发生改变)
    db.session.commit()

查询

  • filter_by精确查询
    # 查询name是wang的所有对象
    User.query.filter_by(name='wang').all()
  • frist返回第一个对象
    # 查询name是wang的第一个对象
    User.query.filter_by(name='wang').first()
  • all返回查询到所有对象(返回一个查询集合)
    # 查询name是wang的所有对象
    User.query.filter_by(name='wang').all()
  • filter模糊查询
    # 查询name结尾是‘g’的所有数据
    User.query.filter(User.name.endswith('g')).all()
  • get查询主键
    # 查询主键ID为 1 的对象
    User.query.get(1)
  • 逻辑非查询
    # 返回name不是‘wang’的所有用户
    User.query.filter(User.name!='wang').all()
  • 逻辑与,需要导入and
    # 查询所有name是wang的并且emali以‘163.com’结尾的用户
    from sqlalchemy import and_
    User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
  • 逻辑或,需要导入or_
    # 查询所有name是wang或者emali以‘163.com’结尾的用户
    from sqlalchemy import or_
    User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
  • not_取反操作
    # name是chen的都不要,及取name是‘chen’的反
    from sqlalchemy import not_
    User.query.filter(not_(User.name=='chen')).all()

一般查询操作总汇(包括其他部分查询)

 """
    查询所有用户数据
        User.query.all()
    查询有多少个用户
        User.query.count()
    查询第1个用户
        User.query.first()
    查询id为4的用户[3种方式]
        User.query.get(4)
        User.query.filter(User.id == 4).first()
        User.query.filter_by(id=4).first()
    查询名字结尾字符为g的所有数据[开始/包含]
        User.query.filter(User.name.endswith('g')).all()
        User.query.filter(User.name.startswith('g')).all()
        User.query.filter(User.name.contains('g')).all()
    查询名字不等于wang的所有数据[2种方式]
        User.query.filter(not_(Usme == 'wang')).all()
        User.query.filter(User.name != 'er.nawang').all()
    查询名字和邮箱都以 li 开头的所有数据[2种方式]
        User.query.filter(and_(User.name.startswith("li"), User.email.startswith("li"))).all()
        User.query.filter(User.name.startswith("li"), User.email.startswith("li")).all()
    查询password是 `123456` 或者 `email` 以 `itheima.com` 结尾的所有数据
        [User: 1 wang, User: 5 tang, User: 8 liu]
    查询id为 [1, 3, 5, 7, 9] 的用户列表
        User.query.filter(User.id.in_([1,3,5,7,9])).all()
    查询name为liu的角色数据
        user = User.query.filter(User.name == "liu").first()
        Role.query.get(user.role_id)
    查询所有用户数据,并以邮箱排序
        User.query.order_by(User.email).all()
        User.query.order_by(User.email.desc()).all()  倒序
    每页3个,查询第2页的数据
        User.query.paginate(2, 3, False).items
    """

 

错误之处欢迎指出


http://www.niftyadmin.cn/n/1585951.html

相关文章

win7选择默认程序出错

Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Unknown]“AlwaysShowExt””"“QueryClassStore””"“TypeOverlay””"[HKEY_CLASSES_ROOT\Unknown\DefaultIcon]hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\00…

多任务-多线程

注意: 因为python存在全局解释器锁(GIL)所以纯Cpython不存在真正的多任务。想要实现多任务可以使用c模块实现真正的多任务。(笔记 多任务-* 不考虑GIL的存在,认为python存在多任务)。 每个进程默认开启一条主线程可以自己开辟多条…

js如何获取当前时间并对时间进行比较?

2019独角兽企业重金招聘Python工程师标准>>> //var yourtimedocument.getElementById(begin_time).value; var yourtime2009-12-10;yourtime yourtime.replace(/-/g,"/");//替换字符,变成标准格式 var d2new Date();//取今天的日期 var d1 n…

数据挖掘学习(一)环境搭建

创建虚拟环境 mkvirtualenv -p python3 sp 安装依赖包 使用包 matplotlib2.2.2 numpy1.14.2 pandas0.20.3 TA-Lib0.4.16 tables3.4.2 jupyter1.0.0 安装(我存放在文件中) pip install -r requirements.txt Ta-Lib安装会出现问题,需要先安装依…

git设置默认编辑为vim

f you want to set the editor only for Git, do either (you don’t need both): Set core.editor in your Git config: git config --global core.editor "vim" Set the GIT_EDITOR environment variable: export GIT_EDITORvim

数据挖掘基础-初步认识-matplotlib

实现一个简单的 matplotlib 画图(Shift Enter 执行) matplotlib 三层结构 容器层 容器层由Canvas、Figure、Axes三部分组成 Canvas 位于最底层的系统层, 充当画板,即放置Figure的工具 Figure 是Canvas上方的第一层&#x…

jsp页面乱码

转载于:https://www.cnblogs.com/Yxxxxx/p/6828080.html

数据挖掘基础-使用matplotlib实现简单图形

折线图 保存简单折线图 import matplotlib.pyplot as plt plt.figure(figsize(20, 8), dpi80) # figsize指定长高, dpi像素 # 生成fig对象 plt.plot([1, 0, 9], [4, 5, 6]) path test1.png plt.savefig(path) # plt.show() # 注意:plt.show()会释放figure资源&…