zoukankan      html  css  js  c++  java
  • Flask 第六话之数据库 -- SQLalchemy

    一、sqlalchemy原生语句操作

    from sqlalchemy import create_engine
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    # 判断是否链接成功
    conn = engine.connect()
    
    result = conn.execute('SELECT * FROM shop_area')
    
    print(result.fetchone())

     二、定义一个简单的ORM模型

    第一步:用declarative_base根据engine创建一个ORM基类

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    engine = create_engine(DB_URL)
    Base = declarative_base(engine)

    第二步:用Base作为基类来定义自己的ORM类,首先定义__tablename__ = 'person'指定数据库表名。

    class Person(Base):
        __tablename__ = 'person' # 表名

    第三步:创建数据库映射的字段

    from sqlalchemy import create_engine,Column,Integer,String
    class Person(Base):
        __tablename__ = 'person' # 表名
        # 第二步:定义字段对象
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)

    第四步:将自己定义的ORM类映射到数据库中

    Base.metadata.create_all()

     三、常用数据类型

    1. Integer:整型,映射到数据库中是int类型。

    2. Float:浮点类型,映射到数据库中是float类型。它占据的32位。

    3. Double:双精度浮点类型,映射到数据库中是double类型,占据64位。

    4. String:可变字符类型,映射到数据库中是varchar类型。

    5. Boolean:布尔类型,映射到数据库中的是tinyint类型。

    6. DECIMAL:定点类型。是专门为了解决浮点类型精度丢失的问题的。在存储钱相关的字段的时候建议大家都使用这个数据类型。并且这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位。

    7. Enum:枚举类型。指定某个字段只能是枚举中指定的几个值,不能为其他值。在ORM模型中,使用Enum来作为枚举。

    8. Date:存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用`datetime.date`来指定。

    9. DateTime:存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用`datetime.datetime`来指定。

    10. Time:存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用`datetime.time`来指定。

    11. Text:存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型。

    12. LONGTEXT:长文本类型,映射到数据库中是longtext类型。

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()
    
    
    # 第一步:创建一个ORM模型
    from sqlalchemy import Column,Integer,String,DECIMAL,Boolean,Enum,Date,DateTime,Time,Text
    from sqlalchemy.dialects.mysql import LONGTEXT
    import enum,datetime
    class TagEnum(enum.Enum):
        python = "python"
        java = "java"
        django = "diango"
    
    class Person(Base):
        __tablename__ = 'person' # 表名
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)
        country = Column(String(20))
        # DECIMAL(总位数,小数点后的位数)
        price = Column(DECIMAL(20,9))
        # 布尔类型
        is_delete = Column(Boolean)
        # 枚举类型方式一
        tag1 = Column(Enum("python",'java','php'))
        # 枚举类型方式二
        tag2 = Column(Enum(TagEnum))
        # 时间
        # 2017-10-05
        create_time1 = Column(Date)
        # 2017-10-05 23:26:58
        create_time2 = Column(DateTime)
        # 23:26:58
        create_time3 = Column(Time)
        # 文本类型
        content = Column(Text)
        lcontent = Column(LONGTEXT)
    
    # 删除数据表 === 删除数据库表
    Base.metadata.drop_all()
    # 创建数据表 === 只会映射一次到数据库中
    Base.metadata.create_all()
    
    per = Person(
        name = 'xxx',
        age = 18,
        country = 66,
        price = 6.555555555,
        is_delete = True,
        tag1 = "python",
        tag2 = TagEnum.python,
        create_time1 = datetime.date(2017,10,5),
        create_time2 = datetime.datetime(2017,10,5,23,26,58),
        create_time3 = datetime.time(23,26,58),
        content = "我可以存储6万多个字符串",
        lcontent = "我比6万多个字符串还多"
    )
    session.add(per)
    session.commit()

     四、Column常用参数

    1.default:默认值
    2.nullable:是否为空
    3.primary_key:是否为主键
    4.unique:是否唯一
    5.autoincrement:是否自动增长
    6.onupdate:更新的时候执行的函数
    7.name:该属性再数据库中的字段映射

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()
    
    
    # 第一步:创建一个ORM模型
    from sqlalchemy import Column,Integer,String,DateTime
    from datetime import datetime
    class Person(Base):
        __tablename__ = 'person' # 表名
        id = Column(Integer,primary_key=True,autoincrement=True)
        # 数据库字段名就变成了my_title
        title = Column(String(50),name="my_title",nullable=False)
        create_time = Column(DateTime,default=datetime.now())
        update_date = Column(DateTime,onupdate=datetime.now)
        read_count = Column(Integer,default=0,nullable=False)
    
    # 删除数据表 === 删除数据库表
    Base.metadata.drop_all()
    # 创建数据表 === 只会映射一次到数据库中
    Base.metadata.create_all()
    
    # 添加数据
    per = Person(title = "aaa")
    session.add(per)
    session.commit()
    
    # 修改数据 === 测试onupdate,只有更新时update_date字段才有数据修改
    # p = session.query(Person).first()
    # p.title = "s5s5"
    # session.commit()

     五、query可用参数

    # 模型对象
    # aces = session.query(Article).all()
    # print(aces)
    
    # 模型属性
    # aces = session.query(Article.title,Article.price).all()
    # print(aces)
    
    # 聚合函数
    from sqlalchemy import func
    aces = session.query(func.count(Article.id)).first()
    print('行数量',aces)
    aces1 = session.query(func.avg(Article.price)).first()
    print('求平均值',aces1)
    aces2 = session.query(func.max(Article.price)).first()
    print('求最大值',aces2)
    aces3 = session.query(func.min(Article.price)).first()
    print('求最小值',aces3)
    aces4 = session.query(func.sum(Article.price)).first()
    print('求和',aces4)

    六、filter过滤条件

    # equal
    a1 = session.query(Article).filter(Article.id == 1).first()
    # not equal
    a2 = session.query(Article).filter(Article.id != 1).all()
    # like && ilike(不区分大小写)
    a3 = session.query(Article).filter(Article.title.like('title%')).all()
    # in
    a4 = session.query(Article).filter(Article.title.in_(['title0','title2'])).all()
    # not in
    a5 = session.query(Article).filter(~Article.title.in_(['title0','title2'])).all()
    # is null
    a6 = session.query(Article).filter(Article.content == None).all()
    # is not null
    a7 = session.query(Article).filter(Article.content != None).all()
    # and
    from sqlalchemy import and_
    a81 = session.query(Article).filter(and_(Article.title == 'aaa',Article.content == 'aaa')).all()
    a82 = session.query(Article).filter(Article.title == 'aaa',Article.content == 'aaa').all()
    # or
    from sqlalchemy import or_
    a9 = session.query(Article).filter(or_(Article.title == 'aaa',Article.content == 'aaa')).all()

     八、1对N的关系创建

    from sqlalchemy import Column,Integer,String,Text,ForeignKey
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()
    
    # 用户表
    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer,primary_key=True,autoincrement=True)
        username = Column(String(50),nullable=False)
    
    # 文章表
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        content = Column(Text,nullable=False)
        uid = Column(Integer,ForeignKey("user.id",ondelete="CASCADE"))
    
        # 创建(N对1)或(1对n)的关系 Article1,Article2 ===》 User
        author = relationship("User",backref = "articles")
        def __repr__(self):
            return "Article_title=%s"%self.title
    
    # 删除数据表 === 删除数据库表
    Base.metadata.drop_all()
    # 创建数据表 === 只会映射一次到数据库中
    Base.metadata.create_all()
    
    
    # 1个用户对个文章
    """  将文章添加到用户对象中去
    # 创建用户对象
    u = User(username = "小海椒")
    # 创建两个文章对象
    a1 = Article(title = "t1",content='11111111111111111111')
    a2 = Article(title = "t2",content='22222222222222222222')
    # 将文章分别添加到用户对象中
    u.articles.append(a1)
    u.articles.append(a2)
    # 将用户对象添加到session中
    session.add(u)
    session.commit()
    """
    
    """ 将用户添加到文章对象中去
    u = User(username = "小海椒2")
    a = Article(title = "t3",content = "33333333333333")
    a.author = u
    
    session.add(a)
    session.commit()
    """

    九、1对1的创建关系

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()
    
    from sqlalchemy import Column,Integer,String,Text,ForeignKey
    
    from sqlalchemy.orm import backref
    
    # 用户表
    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer,primary_key=True,autoincrement=True)
        username = Column(String(50),nullable=False)
    
    # 用户信息表
    class UserExtend(Base):
        __tablename__ = 'user_extend'
        id = Column(Integer, primary_key=True, autoincrement=True)
        school = Column(String(50))
        uid = Column(Integer,ForeignKey('user.id'))
    
        # 创建1对1的关系
        user = relationship("User",backref = backref("extend",uselist=False))
    
    
    # 删除数据表 === 删除数据库表
    Base.metadata.drop_all()
    # 创建数据表 === 只会映射一次到数据库中
    Base.metadata.create_all()
    
    # 1个用户对1个用户信息
    u = User(username = "小黑")
    extend1 = UserExtend(school="北京广播电视大学")
    
    u.extend = extend1
    session.add(u)
    session.commit()

    十、多对多的创建关系

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker,relationship,backref
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()
    
    from sqlalchemy import Column,Integer,String,ForeignKey,Table
    
    article_tag = Table(
        "article_tag",  # 表名
        Base.metadata,
        Column('article_id',Integer,ForeignKey("article.id"),primary_key=True),
        Column('tag_id',Integer,ForeignKey("tag.id"),primary_key=True)
    )
    
    # 文章表
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
    
        # tags = relationship("Tag",backref='articles',secondary=article_tag)
    
    
    # 文章标签
    class Tag(Base):
        __tablename__ = 'tag'
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
    
        articles = relationship("Article",backref='tags',secondary=article_tag)
    
    # # # # 删除数据表 === 删除数据库表
    # Base.metadata.drop_all()
    # # # # 创建数据表 === 只会映射一次到数据库中
    # Base.metadata.create_all()
    
    
    """
    1、定义两个多对多的模型
    2、使用Table定义一个中间表(包含两个模型的外键字段并做复合主键)
    3、随便再两个需要做多对多模型中选择一个定义relationship属性来绑定三者关系
    例:再Article模型中
        tags = relationship("Tag",backref='articles',secondary=article_tag)
    """
    
    # 多对多添加数据
    # a1 = Article(title="Scrapy能用于那些地方?")
    # a2 = Article(title="Flask和Django哪个更适用于web开发?")
    #
    # t1 = Tag(name='python')
    # t2 = Tag(name='flask')
    #
    # a1.tags.append(t1)
    # a1.tags.append(t2)
    #
    # a2.tags.append(t1)
    # a2.tags.append(t2)
    #
    # session.add(a1)
    # session.add(a2)
    #
    # session.commit()
    
    
    # 多对多查询
    a = session.query(Article).first()
    for i in a.tags:
        print(i.name)
    
    t = session.query(Tag).first()
    print(t.articles)

     十一、排序的三种方式

    为防止每次都需要连接数据库代码做出文件分离:DB/db.py

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    
    HOSTNAME = '127.0.0.1'
    PORT = 3306
    DATABASE = 'db_demo'
    USERNAME = 'root'
    PASSWORD = '123456'
    
    # 链接数据库的字符串,固定格式
    DB_URL = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(
        username = USERNAME,
        password = PASSWORD,
        host = HOSTNAME,
        port = PORT,
        db = DATABASE,
    )
    
    engine = create_engine(DB_URL)
    
    Base = declarative_base(engine)
    
    session = sessionmaker(engine)()

    三种方式:

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    class User(Base):
        __tablename__='user'
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
    
    # 文章表
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        create_time = Column(DateTime,default=datetime.now(),nullable=False)
        uid = Column(Integer,ForeignKey("user.id"))
        # 方式三:可以在创建外键关系时通过backref参数指定字段排序方式
        author = relationship(
            "User",
            backref=backref(
                'articles',
                order_by=create_time.desc()
            )
        )
        # 方式二:可以指定查询排序方式
        # __mapper_args__ ={
        #     "order_by":create_time.desc()
        # }
    
        def __repr__(self):
            return "<article {} {} {}>".format(self.id,self.title,self.create_time)
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_article(title):
        # 添加数据
        article = Article(title=title)
        session.add(article)
        session.commit()
    
    def add_article2():
        article1 = Article(title='ccccccccc')
        article2 = Article(title='ddddddddd')
        user = User(name='小红')
    
        user.articles = [article1,article2]
        session.add(user)
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
    
        # add_article('xxx6')
    
        # add_article2()
    
        # 第一种方式:代码中指定排序方式
        # 正序排序
        # articles1 = session.query(Article).order_by(Article.create_time).all()
    
        # 倒序排序
        # articles3 = session.query(Article).order_by(Article.create_time.desc()).all()
    
        # 第二中方式:模型中指定排序方式
        """
        __mapper_args__ ={
            "order_by":create_time.desc()
        }
        """
        # articles4 = session.query(Article).all()
    
    
        # 第三种方式:
        """
        author = relationship(
            "User",
            backref=backref(
                'articles',
                order_by=create_time.desc()
            )
        )
        """
        u = session.query(User).first()
        print(u.articles)

     十二、limit、offset,slice、切片

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    # 文章表
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        create_time = Column(DateTime,default=datetime.now(),nullable=False)
    
        def __repr__(self):
            return "<Article {}>".format(self.title)
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_article():
        # 添加数据
        for item in range(99):
            article = Article(title="文章标题{}".format(item))
            session.add(article)
    
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
    
        # add_article()
    
        # limit:可以查找的时候限制只查找几条 1-10
        articles1 = session.query(Article).limit(10).all()
        # offset:可以限制查找数据的时候过滤前面多少条 倒叙10-20
        articles2 = session.query(Article).order_by(Article.id.desc()).offset(10).limit(10).all()
        # 切片:可以对query对象使用切片来确定想要拿到的数据 倒叙最后10条数据
        articles3 = session.query(Article).order_by(Article.id.desc()).slice(0, 10).all()
        articles4 = session.query(Article).order_by(Article.id.desc())[0:10]

    十三、查询懒加载

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    class User(Base):
        __tablename__ = "user"
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
    
    # 文章表
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        create_time = Column(DateTime,default=datetime.now(),nullable=False)
        uid = Column(Integer,ForeignKey("user.id"))
    
        articles = relationship("User",backref= backref("articles",lazy="dynamic"))
    
        def __repr__(self):
            return "<Article {}>".format(self.title)
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_data():
        # 添加数据
        u = User(name="小黑")
    
        article_li = []
        for item in range(100):
            article_li.append(Article(title="文章标题{}".format(item)))
        u.articles = article_li
        session.add(u)
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
        # add_data()
    
        u = session.query(User).first()
        # AppenderQuery对象继承Query可以使用Query的所有方法对sql进行过滤
        res = u.articles.filter(Article.id<10).all()
        # 并且处理查询,也可以使用这个Query对象继续添加数据
        u.articles.append(Article(title="文章标题{}".format(1000)))
        session.add(u)
        session.commit()

     十四、group_by and having

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey,Enum,func
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    class User(Base):
        __tablename__ = "user"
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
        age = Column(Integer,default=0)
        gender = Column(Enum("male","female","secert"))
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_data():
        # 添加数据
        u1 = User(name="小河", age=18, gender="male")
        u2 = User(name="小马", age=18, gender="female")
        u3 = User(name="张三", age=19, gender="female")
        u4 = User(name="黑核", age=25, gender="secert")
        u5 = User(name="流弊", age=36, gender="male")
    
        session.add_all([u1, u2, u3, u4, u5])
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
        # add_data()
    
        # group_by === [(18, 2), (19, 1), (25, 1), (36, 1)]
        a = session.query(User.age,func.count(User.id)).group_by(User.age).all()
    
        # having === [(18, 2), (19, 1)]
        b = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age<25).all()

    十五、联表查询 -- join

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey,Enum,func
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    class User(Base):
        __tablename__ = "user"
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
    
    
    class Article(Base):
        __tablename__ = "article"
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        create_time = Column(DateTime,nullable=False,default=datetime.now)
        uid = Column(Integer,ForeignKey('user.id'))
    
        articles = relationship("User",backref = backref('articles'))
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_data():
        # 添加数据
        u1 = User(name="小河")
        u2 = User(name="小马")
    
        for i in range(10):
            a = Article(title='xxx{}'.format(i))
            a.articles = u1
            session.add(a)
        session.commit()
    
        for i in range(7):
            a = Article(title='xxx{}'.format(i))
            a.articles = u2
            session.add(a)
        session.commit()
    
    
        session.add_all([u1, u2])
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
        # add_data()
    
        # 找到所有用户,按照发表的文章数量进行排序
        res = session.query(
            User.name,
            func.count(Article.id)
        ).join(
            Article,
            Article.uid == User.id
        ).group_by(
            User.id
        ).order_by(
            func.count(Article.id).desc()
        ).all()
    
        print(res)

    十六、子查询使用 -- subquery

    from sqlalchemy import Column,Integer,String,DateTime,ForeignKey,Enum,func
    from sqlalchemy.orm import relationship,backref
    from DB.db import session,Base
    from datetime import datetime
    
    class User(Base):
        __tablename__ = "user"
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50),nullable=False)
        city = Column(String(50),nullable=False)
        age = Column(Integer,default=0)
    
        def __repr__(self):
            return "< User {}>".format(self.name)
    
    
    def db_init():
        # # # # 删除数据表 === 删除数据库表
        Base.metadata.drop_all()
        # # # # 创建数据表 === 只会映射一次到数据库中
        Base.metadata.create_all()
    
    def add_data():
        # 添加数据
        u1 = User(name="小河",city="重庆",age=18)
        u2 = User(name="小白",city="北京",age=19)
        u3 = User(name="小红",city="河北",age=17)
        u4 = User(name="小慧",city="重庆",age=18)
        u5 = User(name="小黑",city="江苏",age=20)
    
        session.add_all([u1, u2,u3,u4,u5])
        session.commit()
    
    if __name__ == '__main__':
        # db_init()
        # add_data()
    
    # 寻找小河同城同年龄的人
        u = session.query(User).filter(User.name=='小河').first()
        us = session.query(User).filter(User.age == u.age,User.city == u.city).all()
    
    # subquery实现子查询
        # 设置子查询语句
        subs = session.query(
            User.name.label('name'),
            User.city.label('city'),
            User.age.label('age')
        ).filter(
            User.name == "小河"
        ).subquery()
    
        # c是column的简写固定属性
        result = session.query(
            User
        ).filter(
            User.city == subs.c.city,
            User.age == subs.c.age
        ).all()
    
        print(result)
  • 相关阅读:
    OpenDiscussion_DataDrivenDesign
    WPF Auto LogOff
    Visual Studio模板
    我的TDD实践---UnitTest单元测试
    我的TDD实践---TDD概念篇
    我的TDD实践---SVN架设篇
    我的TDD实践---CI持续集成
    CSharpThinking---C#版本总结(附加三)
    CsharpThinking---代码契约CodeContract(八)
    c++文件偏移
  • 原文地址:https://www.cnblogs.com/lee-xingxing/p/12372923.html
Copyright © 2011-2022 走看看