• Flask-SQLAchemy


    SQLALchemy, ORM框架(详细点我

    作用: 帮助我们使用类和对象快速实现数据库操作。

    数据库:
      - 原生:
        - MySQLdb
        -不支持python3
      - pymysql
        -支持python 3/2
      - ORM框架
        - SQLAlchemy

    创建表

    import datetime
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column,UniqueConstraint
    from sqlalchemy import Integer,String,DateTime,ForeignKey
    from sqlalchemy.orm import relationship
    from engine import engine
    
    Base = declarative_base()
    
    #类名就相当于表名
    class Userinfo(Base):
    	__tablename__ = 'userinfo'
    
    	id = Column(Integer, primary_key=True, autoincrement=True)
    	name = Column(String(32),index=True,nullable=True)
    	pwd = Column(Integer,nullable=True)
    	dept_id = Column(Integer,ForeignKey('dept.id'))
    	c_time = Column(DateTime,default=datetime.datetime.now())
    
    	#在表里面不生成字段,就是方便查询和添加数据用
    	dp = relationship('Dept', backref='us')
    
    class Dept(Base):
    	__tablename__ = 'dept'
    	id = Column(Integer, primary_key=True, autoincrement=True)
    	name = Column(String(32),index=True,nullable=True)
    
    
    #创建多对多的关系的时候,SQLAlchemy没有ManytoMany的字段,
    # 就不能帮我们自动的生成第三张表,而是要靠我们自己去创建第三张表,来记录关系
    
    #学生和课程是多对多关系的
    
    class Student(Base):
    	__tablename__ = 'student'
    	id = Column(Integer, primary_key=True, autoincrement=True)
    	name = Column(String(32), index=True, nullable=True)
    
    	cdp = relationship('Course',secondary='student2course',backref='sdp')
    
    
    class Course(Base):
    	__tablename__ = 'course'
    	id = Column(Integer, primary_key=True, autoincrement=True)
    	name = Column(String(32), index=True, nullable=True)
    
    
    class Student2Course(Base):
    	__tablename__ = 'student2course'
    
    	id = Column(Integer, primary_key=True, autoincrement=True)
    	student_id = Column(Integer,ForeignKey('student.id'))
    	course_id = Column(Integer,ForeignKey('course.id'))
    
    	__table_args__ = (
    		#联合唯一
    		UniqueConstraint('student_id', 'course_id', name='sc_id'),
    		#联合
    		# Index('ix_id_name', 'name', 'extra'),
    	)
    
    
    #根据类创建数据库,需要数据库的连接
    
    def create_all():
    	Base.metadata.create_all(engine)
    
    def drop_all():
    	Base.metadata.drop_all(engine)
    
    
    if __name__== '__main__':
    	# drop_all()
    	create_all()
    

    连接数据库

    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker,scoped_session
    engine = create_engine(
    		'mysql+pymysql://root:123456789@127.0.0.1:3306/sqlalchemydb?charset=utf8',
    		max_overflow = 0,
    		pool_size = 5,
    		pool_timeout = 10,
    		pool_recycle = -1,
    	)
    
    #也需要要数据的连接
    SessionFactory = sessionmaker(bind=engine)
    # scoped_session 是基于 threading.local();从连接池中取一个连接放入自己的线程的空间里面
    # 所以多个线程,并发的时候,也是为每个线程自己的空间内有自己的一条连接,这样就不冲突了。
    session = scoped_session(SessionFactory)
    
    
    #按照session = SessionFactory() 这样的形式的时候,在每一次线程来的时候,
    # 都需要每次都从连接池中获取连接
    '''
    def task():
    	session = SessionFactory()
    	session.query(Student).all()
    	session.close()
    
    from threading import Thread
    
    for i in range(20):
    	t = Thread(target=task)	
    	t.start()
    '''
    
    
    '''
    session = scoped_session(SessionFactory)
    
    def task():
    	session.query(Student).all()
    	session.remove()    把自己线程空间内的连接删除掉。也就是将连接返回给连接池。
    
    from threading import Thread
    
    for i in range(20):
    	t = Thread(target=task)	
    	t.start()
    
    '''
    

    对表的操作

    from SQLAlchemy_Demo import Userinfo,Dept,Student,Student2Course,Course
    from engine import session
    from sqlalchemy.orm import sessionmaker
    #操作用sqlalchemy生成的表
    
    # ############# 执行ORM操作 #############
    #查询
    #filter()里面是一个表达式
    #filter_by()里面是关键字传参数了
    # ret = session.query(Userinfo).filter(Userinfo.id>2).all()
    # ret = session.query(Userinfo).filter_by(id=2).first()
    # print(ret)
    
    #增加数据
    #一个对象就代表着一行数据
    # obj = Userinfo(name='alex',pwd=123,dept_id=1)
    # session.add(obj)
    #批量的添加数据
    # session.add_all([
    # 	Userinfo(name='db',pwd=123,dept_id=1),
    # 	Userinfo(name='xiaodong',pwd=123,dept_id=1),
    # ])
    # session.commit()
    # session.close()
    
    #删除 .delete()
    # session.query(Userinfo).filter(Userinfo.id >3).delete()
    # session.commit()
    # session.close()
    
    #修改 update({})
    # session.query(Userinfo).filter(Userinfo.id ==1).update({"name":"阿辉"})
    #synchronize_session=False就可以字符串的拼接了;默认的是数字的拼接。; Userinfo.name可以用表里面的数据
    # session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.name:Userinfo.name+'帅逼'},synchronize_session=False)
    # session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.pwd:Userinfo.pwd+999})
    # session.commit()
    # session.close()
    
    
    #常用的操作
    # 分组  后面跟条件 having
    
    # from sqlalchemy.sql import func
    # ret = session.query(Userinfo).group_by(Userinfo.extra).all()
    #上面这查不了,因为分组后每组后多个,不知道给你返回哪一个,需要你自己来指定。
    # ret = session.query(
    # func.max(Userinfo.id),
    # ).group_by(Userinfo.dept_id).having(func.max(Userinfo.id) >2).all()
    # print(ret)
    
    
    #FK 连表操作   query要查询哪张表里面的什么数据
    # on 条件      Userinfo.dept_id == Dept.id       #join -- inner join
    # user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id).all()
    
    # isouter=True  -- > LEFT OUTER JOIN --  LEFT JOIN
    # user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True).all()
    # for item in user_data:
    # 	print(item.id,item.username,item.name)
    
    # print(session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True))
    
    # ret = session.query(Dept).filter(Dept.name == '销售').first()
    # print(ret)
    
    #FK关系表
    #创建一个名称为: IT部门,再在该部门中添加一个员工:小光
    #第一种方式:
    	# dept_obj = Dept(name='IT部门')
    	# session.add(dept_obj)
    	# session.commit()
    	#只要commit后 dept_obj这个创建的对象就是当前添加到表里面的对象
    	# dept_id = dept_obj.id
    	# print(dept_id)
    	# user_obj = Userinfo(name='小光',dept_id=dept_id,pwd=123)
    	# session.add(user_obj)
    	# session.commit()
    	# session.close()
    #第二种通过relation字段
    # user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部门'))
    #
    # session.add_all(user_obj)
    # session.commit()
    
    #创建一个名称为: IT部门,再在该部门中添加一个员工:小2,小3,小4
    #以上的这种简单的方法就不可取了。
    #user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部门'))
    # user_objs = Userinfo(name='小光02',pwd=123,dp=Dept(name='IT部门'))
    #这样就生成了两个IT部门,分别在对应的添加人。
    #这样要通过反向生成了
    # obj=Dept(name='IT部门01')
    # obj.us = [Userinfo(name='小2',pwd=123),Userinfo(name='小3',pwd=123)]
    #
    # session.add(obj)
    #
    # session.commit()
    # session.close()
    
    #ManytoMany  多对多关系表
    
    #添加上python课程的小辉和小黑,上Linux的小黑,以及上go的小龙到数据库中
    #方式一,自己添加到三张表中
    # session.add_all([Student(name='小辉'),Student(name='小黑'),Student(name='小龙')])
    
    # session.add_all([Course(name='Python'),Course(name='Linux'),Course(name='go')])
    # session.add_all([Student2Course(student_id=6,course_id=6),Student2Course(student_id=7,course_id=6),Student2Course(student_id=7,course_id=7),Student2Course(student_id=8,course_id=8)])
    # session.commit()
    # session.close()
    
    
    #方式二:
    # 创建一个新的课程,创建2个学生,并且为两个学生选取新创建的课程
    
    # c_obj = Course(name='java')
    # c_obj.sdp =[Student(name='01'),Student(name='02')]
    #
    # session.add(c_obj)
    #帮我们在三张表中创建数据
    # session.commit()
    # session.close()
    
    
    #正常查询的话,需要自己不断的连表
    #查询上python课程的所有学生的姓名
    # p_obj = session.query(Student2Course.student_id,Course.name,Student.name).join(Course,Student2Course.course_id ==Course.id).join(Student,Student2Course.student_id == Student.id).filter(Course.name=='python').all()
    # print(p_obj)
    
    
    # 上面的查询需要自己连表,比较麻烦 因此用relationship字段来查询,跟FK的相似。
    
    c_obj = session.query(Course).filter(Course.name=='python').first()
    ret = c_obj.sdp
    for item in ret:
    	print(item.name)
    

      

    总结:

    在flask中使用 flask-sqlalchemy的步骤:
    		1.先在__init__.py文件中导入并实例化SQLAlchemy
    			from flask_sqlalchemy import SQLAlchemy
    			db = SQLAlchemy()    实例化的db里面 什么的有(SQLAlchemy相关的操作), 但是就是没有数据库的连接,因此必须要初始化 
    			注意:
    				-在外面实例化 -- db = SQLAlchemy() 
    				-必须在导入蓝图之前 (因为要导入db,从而操作数据库的)
    				-必须导入models.py(这样才能自动的帮我们去找到对应的类,去生成对应的表)
    
    		2. 初始化 (对取app里面的配置文件,读取数据库的连接)
    			db.init_app(app)
    
    		3.在配置文件中写入数据库连接的配置
    			SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456789@127.0.0.1:3306/sqlalchemydb?charset=utf8'
    			SQLALCHEMY_POOL_SIZE = 10
    			SQLALCHEMY_MAX_OVERFLOW = 2
    
    		4.创建models.py中的类(对应数据库的表)
    			在与__init__同级目录下创建models.py
    			注意:此时的类必须要继承db.Model
    			class Userinfo(db.Model):
    				__tablename__ = 'userinfo'
    
    				id = Column(Integer, primary_key=True, autoincrement=True)
    				name = Column(String(32),index=True,nullable=True)
    				pwd = Column(Integer,nullable=True)
    				dept_id = Column(Integer,ForeignKey('dept.id'))
    				c_time = Column(DateTime,default=datetime.datetime.now())
    		5.然后再最外面创建一个独立的脚本,用来生成表。
    			注意:要使用app上下文,拿到里面的app
    			#要应用到app上文管理
    			from crm import db,create_app
    
    			app = create_app()
    			app_ctx = app.app_context()
    
    			with app_ctx:
    				# with 对象 的时候就会自动的触发类的__enter__ 方法,然后执行下面的代码,最后执行__exit__
    
    				#__enter__是将app_ctx通过;LocalStack放入Local中,
    
    				db.create_all()  #会调用LocalStack 从Local中获取app,然后再从app中获取配置。
    
    				#__exit__ 是将当前的app_ctx对象从Local中移除掉
    
    		6.基于ORM对数据库进行操作。
    			要导入db
    			db.session 就相当于 以前使用的session了
    			db.session.add(...)	
    			#SQLAlchemy的应用:
    			# from crm import db
    			# from crm import models
    			# userobj = models.Userinfo(name='小辉', pwd=123, dept_id=12)
    			# userobj.dp = models.Dept(name='销售')
    			# db.session.add(userobj)
    			# db.session.commit()
    			# db.session.remove()
    				
    

      

      

      

  • 相关阅读:
    表单输入框黏贴自动过滤转义实例
    前端性能优化成神之路-浏览器缓存机制详解
    前端性能优化成神之路-HTTP压缩开启gzip
    前端性能优化成神之路—重绘与回流
    前端性能优化成神之路—图片相关的优化
    ES5-ES6-ES7_集合Set和Map
    ES5-ES6-ES7_解构赋值
    ES5-ES6-ES7_函数的扩展
    ES5-ES6-ES7_数值的扩展
    ES5-ES6-ES7_字符串与JOSN格式的数据相互转换以及深度克隆新对象
  • 原文地址:https://www.cnblogs.com/zenghui-python/p/11684594.html
Copyright © 2020-2023  润新知