• SQLAlchemy关联表一对多关系的详解


    目录

    ORM关系之一对多

    示例1 

    代码刨析 

    示例2

     代码刨析


    ORM关系之一对多

    mysql级别的外键,还不够爽,必须拿到一个表的外键,然后通过这个外键再去另外一张表中查找,这样太麻烦了。

    SQLAlchemy提供了一个relationship,这个类可以定义属性,以后在访问相关联的表的时候就直接可以通过属性访问的方式就可以访问得到了。

    另外,可以通过backref来指定反向访问的属性名称。newss是指有多篇新闻。他们之间的关系是一个“一对多”的关系。

    数据库层面

    在数据库中,一对多关系通常通过在多的一方表中添加一个外键列,该列引用了另一方的主键。例如,在一个博客系统中,一个用户可以有多篇文章,那么在文章表中通常会包含一个指向用户表的外键。

    ORM 层面

    在 ORM 中,一对多关系通常通过在一个类中定义一个关联属性来实现。这个关联属性指明了与之相关联的类,以及在数据库中如何表示这种关系。

    在 SQLAlchemy 中,可以使用 relationship 来定义一对多关系。比如:

    1. class User(Base):
    2. __tablename__ = 'users'
    3. id = Column(Integer, primary_key=True)
    4. username = Column(String, unique=True, nullable=False)
    5. articles = relationship('Article', back_populates='author', cascade='all, delete-orphan')
    6. class Article(Base):
    7. __tablename__ = 'articles'
    8. id = Column(Integer, primary_key=True)
    9. title = Column(String, nullable=False)
    10. content = Column(String, nullable=False)
    11. author_id = Column(Integer, ForeignKey('users.id'))
    12. author = relationship('User', back_populates='articles')

    查询操作 

    在一对多关系中,可以轻松地通过关联属性来访问相关联的对象。例如,你可以通过 user.articles 访问一个用户的所有文章,或者通过 article.author 访问一篇文章的作者。

    1. # 获取第一个用户的所有文章
    2. user = session.query(User).first()
    3. articles = user.articles
    4. # 获取第一篇文章的作者
    5. article = session.query(Article).first()
    6. author = article.author

    添加与删除 

    在一对多关系中,你可以通过调用关联属性来添加新的对象。例如,你可以通过 user.articles.append(new_article) 将一篇新文章添加到一个用户的文章列表中。

    1. # 创建一个新的文章,并将其关联到第一个用户
    2. new_article = Article(title='New Article', content='Content of the new article')
    3. user.articles.append(new_article)
    4. session.commit()

    还可以通过 user.articles.remove(article) 删除一个用户的某篇文章。

    1. # 删除用户的第一篇文章
    2. article_to_delete = user.articles[0]
    3. user.articles.remove(article_to_delete)
    4. session.commit()

    以下是一个简单的示例,使用 SQLAlchemy 来创建一个用户和文章的一对多关系:

    示例1 

    1. from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
    2. from sqlalchemy.ext.declarative import declarative_base
    3. from sqlalchemy.orm import relationship
    4. Base = declarative_base()
    5. class User(Base):
    6. __tablename__ = 'users'
    7. id = Column(Integer, primary_key=True)
    8. username = Column(String, unique=True, nullable=False)
    9. articles = relationship('Article', back_populates='author', cascade='all, delete-orphan')
    10. class Article(Base):
    11. __tablename__ = 'articles'
    12. id = Column(Integer, primary_key=True)
    13. title = Column(String, nullable=False)
    14. content = Column(String, nullable=False)
    15. author_id = Column(Integer, ForeignKey('users.id'))
    16. author = relationship('User', back_populates='articles')
    17. # 创建数据库连接
    18. engine = create_engine('sqlite:///example.db')
    19. # 创建表格
    20. Base.metadata.create_all(engine)

    代码刨析 

    在这个示例中,我们定义了两个类:UserArticle,并建立了一对多的关系:

    • User 类拥有一个属性 articles,它是一个关系属性,通过 relationship 函数来定义。这个关系会映射到 Article 类,并且通过 back_populates 参数指定了反向关系的属性名为 author

    • Article 类中有一个属性 author,也是一个关系属性,通过 relationship 函数定义。它映射到 User 类,并且通过 back_populates 参数指定了反向关系的属性名为 articles

    在这个示例中,我们通过 relationship 来定义了一对多关系,并且通过 ForeignKey 来建立了外键关系,将 Article 表中的 author_idUser 表中的 id 关联起来。

    这样,一个用户可以拥有多篇文章,而每篇文章只属于一个用户。

    示例2

    1. from sqlalchemy import Column,Integer,String,Text,ForeignKey
    2. from sqlalchemy.orm import relationship
    3. from db_util import Base,Session
    4. class User(Base):
    5. __tablename__ = 't_user'
    6. id = Column(Integer,primary_key=True,autoincrement=True)
    7. uname = Column(String(50),nullable=False,name='name')
    8. # news = relationship('News') # 不友好
    9. def __repr__(self):
    10. return f'{self.id} uname={self.uname}>'
    11. # 1对多 ForeignKey的关键字要建立在 多一边
    12. class News(Base):
    13. __tablename__ = 't_news'
    14. id = Column(Integer,primary_key=True,autoincrement=True)
    15. title = Column(String(50),nullable=False)
    16. content = Column(Text,nullable=False)
    17. uid = Column(Integer,ForeignKey('t_user.id'))
    18. user = relationship('User',backref='news') # 将主表的数据注入到这个字段
    19. def __repr__(self):
    20. return f'{self.id} title={self.title} content={self.content} uid={self.uid}>'
    21. def create_data():
    22. user = User(uname = 'sxt')
    23. news1 = News(title='Python',content='flask',uid = 1)
    24. news2 = News(title='MySQL',content='SQL',uid = 1)
    25. with Session() as ses:
    26. ses.add(user)
    27. ses.commit()
    28. with Session() as ses:
    29. ses.add(news1)
    30. ses.add(news2)
    31. ses.commit()
    32. def query_data():
    33. with Session() as ses:
    34. # news1 = ses.query(News).first()
    35. # print(news1)
    36. # select u.id u.uname from t_news n left join t_user u n.uid = u.id where n.id = 1;
    37. news1 = ses.query(News).first()
    38. uid = news1.uid
    39. user = ses.query(User).first()
    40. print(user)
    41. def query_data2():
    42. # 通地子表查询主表的数据
    43. with Session() as ses:
    44. news1 = ses.query(News).first()
    45. print(news1.user)
    46. def query_data3():
    47. # 通地主表查找子表的数据
    48. with Session() as ses:
    49. user1 = ses.query(User).first()
    50. print(user1.news)
    51. if __name__ == '__main__':
    52. # Base.metadata.create_all()
    53. # create_data()
    54. # query_data()
    55. # query_data2()
    56. query_data3()

     代码刨析

    1. User 类中包括了一个关联属性 news,它通过 relationship 来指明与 News 类的关系。而在 News 类中,使用了 ForeignKey 来建立了对 User 表的外键关联,并通过 relationship 指定了与 User 类的关联关系。

    2. create_data 函数创建了一个用户和两条新闻,并将它们添加到数据库中。

    3. query_data 函数中,你首先查询了一条新闻,然后获取了它的 uid(用户ID),接着通过用户ID查询了相应的用户。

    4. query_data2 函数中,首先查询了一条新闻,然后通过 news1.user 直接访问了与之关联的用户对象。

    5. query_data3 函数中,首先查询了一个用户,然后通过 user1.news 直接访问了与之关联的新闻对象。

  • 相关阅读:
    linuxnfs服务安装与配置实践
    springboot中使用redis管理session
    活动回顾 | 数字外贸私享会【上海站】成功举办
    Kafka系列之:Kafka Connect Configs
    图解计算机的存储器金字塔
    TF-IDF
    Java核心篇,二十三种设计模式(十七),行为型——中介者模式
    【实战详解】如何快速搭建接口自动化测试框架?Python + Requests
    《数据结构》八大排序(详细图文分析讲解)
    系统集成|第九章(笔记)
  • 原文地址:https://blog.csdn.net/m0_67093160/article/details/133324341