美文网首页
SQLAlchemy 教程

SQLAlchemy 教程

作者: TomnJerry | 来源:发表于2018-05-30 23:59 被阅读0次

    ORM( Object Relational Mapping)

    • ORM,又称对象关系映射。简单来说,ORM将数据库中的表与面向对象的语言中的类建立了一种一一映射关系。这样,我们要操作数据库、数据库中的表或者表中的记录,就可以直接通过操作类或者类的实例来完成。

    安装

    • pip install sqlalchemy

    启动MySQL

    • 安装MySQL
    • 安装一个MySQL驱动(如mysqldb)
    • 修改MySQL配置文件 /etc/my.cnf 中的字符集为utf8
    • 启动MySQL服务 service mysqld start
    • 进入MySQL命令行 mysql -u root -p
    • 创建数据库 create database sqlalchemy_test

    SQLAlchemy工作流程

    1. 得到数据库实例
    from sqlalchemy import create_engine
    engine = create_engine('mysql+mysqldb://root@localhost:3306/sqlalchemy_test'[, echo=True]) # 得到数据库实例, echo=True显示sql语句信息
    print 'engine' # Engine(mysql+mysqldb://root@localhost:3306/sqlalchemy_test)
    
    1. 建立会话(建立和MySQL实例沟通的桥梁)
    from sqlalchemy.orm import sessionmaker
    
    Session = sessionmaker(bind=engine)
    session = Session()
    
    1. 描述表结构

    3.1 一对多关系

    • 每篇文章有一个外键指向 users 表中的主键 id
    • 用户与文章的关系为一对多的关系,这个关系是双向的
    • User 中使用 SQLAlchemy 提供的 relationship 描述表之间的关系
    • 所以我们看到上面的两张表中都定义了 relationship
    • SQLAlchemy 提供了 backref 让我们可以只需要定义一个关系:
    articles = relationship('Article', backref='author')
    
    • 添加了这个就可以不用再在 Article 中定义 relationship 了
    • relationship是类与类之间的关系,可以实现类似外键的功能,它与外键不冲突
    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import Column, String, Integer
    
    engine = create_engine('mysql+mysqldb://root@localhost:3306/sqlalchemy_test?charset=utf8')
    Base = declarative_base() # 生成ORM基类,所有表需要继承该类
    
    class User(Base):
        '''Users表'''
        __tablename__ = 'users' # 表名
    
        id = Column(Integer, primary_key=True)
        username = Column(String32), nullable=False, index=True)
        password = Column(String(64), nullable=False)
        email = Column(String(64), nullable=False, index=True)
        articles = relationship('Article')
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.username)
    
    
    class Article(Base):
        '''Article表'''
        __tablename__ = 'articles'
    
        id = Column(Integer, primary_key=True)
        title = Column(String(255), nullable=False, index=True)
        content = Column(Text)
        user_id = Column(Integer, ForeignKey('users.id'))
        author = relationship('User')
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.title)
    

    3.2 一对一关系

    • 在 User 中我们只定义了几个必须的字段, 但通常用户还有很多其他信息,但这些信息可能不是必须填写的,我们可以把它们放到另一张 UserInfo 表中,这样 User 和 UserInfo 就形成了一对一的关系
    • 你可能会奇怪一对一关系为什么不在一对多关系前面?那是因为一对一关系是基于一对多定义的
    class User(Base):
        '''users表'''
        __tablename__ = 'users' # 表名
    
        id = Column(Integer, primary_key=True)
        username = Column(String(32), nullable=False, index=True)
        password = Column(String(64), nullable=False)
        email = Column(String(64), nullable=False, index=True)
        articles = relationship('Article', backref='author')
        userinfo = relationship('UserInfo', backref='user', uselist=False)
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.username)
    
    
    class UserInfo(Base):
        '''userinfo表'''
        __tablename__ = 'userinfos' # 表名
    
        id = Column(Integer, primary_key=True)
        name = Column(String(32))
        qq = Column(String(11))
        phone = Column(String(11))
        link = Column(String(64))
        user_id = Column(Integer, ForeignKey('users.id'))
    

    3.3 多对多关系

    • 一遍博客通常有一个分类,好几个标签
    • 标签与博客之间就是一个多对多的关系
    • 多对多关系不能直接定义,需要分解成俩个一对多的关系
    • 为此,需要一张额外的表来协助完成
    article_tag = Table(
        'article_tag', Base.metadata,
        Column('article_id', Integer, ForeignKey('articles.id')),
        Column('tag_id', Integer, ForeignKey('tags.id'))
    )
    
    
    class Tag(Base):
    
        __tablename__ = 'tags'
    
        id = Column(Integer, primary_key=True)
        name = Column(String(64), nullable=False, index=True)
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.name)
    
    1. 创建表
    if __name__ == '__main__':
        Base.metadata.create_all(engine) # 创建所有表
    
    1. 创建数据并添加提交
    • 安装用来生成测试数据的faker库 pip install faker
        faker = Factory.create()
        Session = sessionmaker(bind=engine)
        session = Session()
    
        faker_users = [User(
            username=faker.name(),
            password=faker.word(),
            email=faker.email(),
        ) for i in range(10)]
        session.add_all(faker_users)
    
        faker_categories = [Category(name=faker.word()) for i in range(5)]
        session.add_all(faker_categories)
    
        faker_tags= [Tag(name=faker.word()) for i in range(20)]
        session.add_all(faker_tags)
    
        for i in range(100):
            article = Article(
                title=faker.sentence(),
                content=' '.join(faker.sentences(nb=random.randint(10, 20))),
                author=random.choice(faker_users),
                category=random.choice(faker_categories)
            )
            for tag in random.sample(faker_tags, random.randint(2, 5)):
                article.tags.append(tag)
            session.add(article)
    
        session.commit()
    
    1. 查询数据
    session.query(User).get(1)
    session.query(User).filter_by(username='Adrienne Miller').first()
    session.query(User).filter(User.username=='Adrienne Miller').first()
    session.query(User).all()
    
    1. 更新数据
    a=session.query(Article).get(10)
    a.title='My test blog post'
    session.add(a)
    session.commit()
    
    a = session.query(Article).get(10)
    a.tags.append(Tag(name='python'))
    session.add(a)
    session.commit()
    
    1. 删除数据
    a =session.query(Article).get(10)
    session.delete(a)
    session.commit()
    

    完整代码

    # coding: utf-8
    
    import random
    from faker import Factory
    
    from sqlalchemy import create_engine, Table
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy import ForeignKey
    from sqlalchemy import Column, String, Integer, Text
    from sqlalchemy.orm import sessionmaker, relationship
    
    
    engine = create_engine('mysql+mysqldb://root@localhost:3306/blog?charset=utf8')
    Base = declarative_base()
    
    
    class User(Base):
    
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True)
        username = Column(String(64), nullable=False, index=True)
        password = Column(String(64), nullable=False)
        email = Column(String(64), nullable=False, index=True)
        articles = relationship('Article', backref='author')
        userinfo = relationship('UserInfo', backref='user', uselist=False)
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.username)
    
    
    class UserInfo(Base):
    
        __tablename__ = 'userinfos'
    
        id = Column(Integer, primary_key=True)
        name = Column(String(64))
        qq = Column(String(11))
        phone = Column(String(11))
        link = Column(String(64))
        user_id = Column(Integer, ForeignKey('users.id'))
    
    
    class Article(Base):
    
        __tablename__ = 'articles'
    
        id = Column(Integer, primary_key=True)
        title = Column(String(255), nullable=False, index=True)
        content = Column(Text)
        user_id = Column(Integer, ForeignKey('users.id'))
        cate_id = Column(Integer, ForeignKey('categories.id'))
        tags = relationship('Tag', secondary='article_tag', backref='articles')
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.title)
    
    
    class Category(Base):
    
        __tablename__ = 'categories'
    
        id = Column(Integer, primary_key=True)
        name = Column(String(64), nullable=False, index=True)
        articles = relationship('Article', backref='category')
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.name)
    
    
    article_tag = Table(
        'article_tag', Base.metadata,
        Column('article_id', Integer, ForeignKey('articles.id')),
        Column('tag_id', Integer, ForeignKey('tags.id'))
    )
    
    
    class Tag(Base):
    
        __tablename__ = 'tags'
    
        id = Column(Integer, primary_key=True)
        name = Column(String(64), nullable=False, index=True)
    
        def __repr__(self):
            return '%s(%r)' % (self.__class__.__name__, self.name)
    
    
    if __name__ == '__main__':
        Base.metadata.create_all(engine)
    
        faker = Factory.create()
        Session = sessionmaker(bind=engine)
        session = Session()
    
        faker_users = [User(
            username=faker.name(),
            password=faker.word(),
            email=faker.email(),
        ) for i in range(10)]
        session.add_all(faker_users)
    
        faker_categories = [Category(name=faker.word()) for i in range(5)]
        session.add_all(faker_categories)
    
        faker_tags= [Tag(name=faker.word()) for i in range(20)]
        session.add_all(faker_tags)
    
        for i in range(100):
            article = Article(
                title=faker.sentence(),
                content=' '.join(faker.sentences(nb=random.randint(10, 20))),
                author=random.choice(faker_users),
                category=random.choice(faker_categories)
            )
            for tag in random.sample(faker_tags, random.randint(2, 5)):
                article.tags.append(tag)
            session.add(article)
    
        session.commit()
    

    相关文章

      网友评论

          本文标题:SQLAlchemy 教程

          本文链接:https://www.haomeiwen.com/subject/hitfsftx.html