Heim >Backend-Entwicklung >Python-Tutorial >SQLAlchemy ORM-Beispieleinführung in Python

SQLAlchemy ORM-Beispieleinführung in Python

高洛峰
高洛峰Original
2017-03-06 14:53:223049Durchsuche

1. Einführung in ORM

ORMs vollständiger Name ist Object Relational Mapping, ein Objekt-Mapping-Beziehungsprogramm. Einfach ausgedrückt ist in unseren objektorientierten Programmen alles ein Objekt, aber wir verwenden Alle Datenbanken sind relational Um konsistente Nutzungsgewohnheiten sicherzustellen, werden das Objektmodell der Programmiersprache und das relationale Modell der Datenbank über ORM abgebildet, sodass wir die Programmiersprache direkt verwenden können, wenn wir die Programmierung verwenden Verwenden Sie einfach das Objektmodell, um die Datenbank zu betreiben, ohne direkt die SQL-Sprache zu verwenden.

python之SQLAlchemy  ORM示例介绍

Vorteile von ORM:

  • Datenzugriffsdetails ausblenden, „geschlossene“ universelle Datenbankinteraktion, der Kern von ORM. Es macht unsere gemeinsamen Datenbankinteraktionen einfach und unkompliziert, ohne dass wir überhaupt über verdammte SQL-Anweisungen nachdenken müssen. Daraus ergibt sich eine rasante Entwicklung.

  • ORM macht es uns einfach und leicht, solide Datenstrukturen aufzubauen.

Nachteile:

  • Automatisierung bedeutet zwangsläufig Mapping und Assoziationsmanagement auf Kosten der Leistung (in den frühen Tagen war das alles Was Leute wie ORM gemeinsam haben). Verschiedene aktuelle ORM-Frameworks versuchen, dieses Problem mit verschiedenen Methoden zu lindern (LazyLoad, Cache), und der Effekt ist immer noch sehr erheblich.

2. SQLAlchemy-Framework und Datenbank-API

In Python ist SQLAlchemy das bekannteste ORM-Framework. Zu den Benutzern gehören bekannte Unternehmen oder Anwendungen wie openstack\Dropbox. Die Hauptbenutzerliste ist http://www.php.cn/

python之SQLAlchemy  ORM示例介绍

Sie müssen die Tabellen zuordnen in der Datenbank selbst in Klassen umwandeln. Dann kann es über das Objekt aufgerufen werden. SQLAlchemy unterstützt nicht nur MYSQL, sondern auch Oracle usw.

Dialekt wird verwendet, um mit der Daten-API zu kommunizieren und verschiedene Datenbank-APIs gemäß unterschiedlichen Konfigurationsdateien aufzurufen, um Vorgänge in der Datenbank auszuführen:

MySQL-Python
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
   
pymysql
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
   
MySQL-Connector
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
   
cx_Oracle
    oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]

SQLAlchemy installieren:

pip install SQLAlchemy

3. Stellen Sie eine Verbindung zur Datenbank her und fragen Sie die

from sqlalchemy import create_engine

#连接数据库,生成engine对象;最大连接数为5个
engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/zcl", max_overflow=5)
print(engine)   #Engine(mysql+pymysql://root:***@127.0.0.1:3306/zcl)
result = engine.execute(&#39;select * from students&#39;) #不用commit(),会自动commit
print(result.fetchall())
Ausgabe:

Engine(mysql+pymysql://root:***@127.0.0.1:3306/zcl)[(1, &#39;zcl&#39;, &#39;man&#39;, 22, &#39;15622341234&#39;, None), (2, &#39;alex&#39;, &#39;man&#39;, 30, &#39;15622341235&#39;, None), (5, &#39;Jack&#39;, &#39;man&#39;, 25, &#39;1351234&#39;, &#39;CN&#39;), (6, &#39;Mary&#39;, &#39;female&#39;, 18, &#39;1341234&#39;, &#39;USA&#39;), (10, &#39;Jack&#39;, &#39;man&#39;, 25, &#39;1351234&#39;, &#39;CN&#39;), (11, &#39;Jack2&#39;, &#39;man&#39;, 25, &#39;1351234&#39;, &#39;CN&#39;), (12, &#39;Mary&#39;, &#39;female&#39;, 18, &#39;1341234&#39;, &#39;USA&#39;), (13, &#39;cjy&#39;, &#39;man&#39;, 18, &#39;1562234&#39;, &#39;USA&#39;), (14, &#39;cjy2&#39;, &#39;man&#39;, 18, &#39;1562235&#39;, &#39;USA&#39;), (15, &#39;cjy3&#39;, &#39;man&#39;, 18, &#39;1562235&#39;, &#39;USA&#39;), (16, &#39;cjy4&#39;, &#39;man&#39;, 18, &#39;1562235&#39;, &#39;USA&#39;), (17, &#39;cjy5&#39;, &#39;man&#39;, 18, &#39;1562235&#39;, &#39;USA&#39;)]

4. Tabellen erstellen

Benutzer- und Farbtabellen erstellen: Beim Erstellen einer Tabelle müssen Sie diese an eine Instanz von MetaData binden.

from sqlalchemy import create_engine, \
    Table, Column, Integer, String, MetaData, ForeignKey

metadata = MetaData()  #相当于实例一个父类

user = Table(&#39;user&#39;, metadata,      #相当于让Table继承metadata类
             Column(&#39;id&#39;, Integer, primary_key=True),
             Column(&#39;name&#39;, String(20)),
             )

color = Table(&#39;color&#39;, metadata,    #表名color
              Column(&#39;id&#39;, Integer, primary_key=True),
              Column(&#39;name&#39;, String(20)),
              )
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", max_overflow=5)

metadata.create_all(engine)  #table已经与metadate绑定
Erstellte Tabelle anzeigen:

python之SQLAlchemy  ORM示例介绍

5. Hinzufügen, Löschen, Ändern und Überprüfen

1. Kommen Sie zuerst. Verstehen Sie das Hinzufügen, Löschen, Ändern und Abfragen nativer SQL-Anweisungen:

from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey,select

metadata = MetaData()

user = Table(&#39;user&#39;, metadata,
             Column(&#39;id&#39;, Integer, primary_key=True),
             Column(&#39;name&#39;, String(20)),
             )

color = Table(&#39;color&#39;, metadata,
              Column(&#39;id&#39;, Integer, primary_key=True),
              Column(&#39;name&#39;, String(20)),
              )
engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/zcl", max_overflow=5)

conn = engine.connect()  #创建游标,当前实例所处状态

# 创建SQL语句,INSERT INTO "user" (id, name) VALUES (:id, :name)
#id号可省略,默认是自增的
# conn.execute(user.insert(), {&#39;id&#39;: 1, &#39;name&#39;: &#39;zcl&#39;})
# conn.close()

# sql = user.insert().values(name=&#39;wu&#39;)  #插入
# conn.execute(sql)
# conn.close()

#删除id号大于1的行,也可以where(user.c.name=="zcl")
# sql = user.delete().where(user.c.id > 1)
# conn.execute(sql)
# conn.close()

# 将name=="wuu"更改为"name=="ed"
# sql = user.update().where(user.c.name == &#39;wuu&#39;).values(name=&#39;ed&#39;)
# conn.execute(sql)
# conn.close()

#查询  下面不能写 sql = user.select... 会曝错
#sql = select([user, ])  #[(1, &#39;zcl&#39;), (9, &#39;ed&#39;), (10, &#39;ed&#39;)]
# sql = select([user.c.id, ])   #[(1,), (9,), (10,)]
sql = select([user.c.name, color.c.name]).where(user.c.id==color.c.id)
# sql = select([user.c.name]).order_by(user.c.name)
# sql = user.select([user]).group_by(user.c.name)

result = conn.execute(sql)
print(result.fetchall())
conn.close()
2. Hinzufügen, Löschen, Ändern und Abfragen über SQLAlchemy (wichtig):

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String
from sqlalchemy.orm import sessionmaker

Base = declarative_base()    #生成一个SqlORM基类(已经封装metadata)
#echo=True可以查看创建表的过程
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", echo=True)

class Host(Base):
    __tablename__ = 'hosts'   #表名为host
    id = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)


Base.metadata.create_all(engine)   #创建所有表结构

if __name__ == '__main__':
    #创建与数据库的会话sessionclass,注意,这里返回给session的是个class类,不是实例
    SessionCls=sessionmaker(bind=engine)
    session=SessionCls()  #连接的实例
    #准备插入数据
    h1 = Host(hostname='localhost', ip_addr='127.0.0.1')    #实例化(未创建)
    h2 = Host(hostname='ubuntu', ip_addr='192.168.2.243', port=20000)
    
    #session.add(h1)   #也可以用下面的批量处理
    #session.add_all([h1,h2])
    #h2.hostname='ubuntu_test'  #只要没提交,此时修改也没问题
    
    #查询数据,返回一个对象
    obj = session.query(Host).filter(Host.hostname=="localhost").first()
    print("-->",obj)
    #[0255631d0cd3bd8030034003e6ba8089]如果上面为.all()
    #f8774803eaa8e8932442db37a173b2b9如果上面为.first()
    
    #如果用.all(),会曝错AttributeError:'list'objecthasnoattribute'hostname'
    #obj.hostname = "localhost_1"   #将主机名修改为localhost_1
    
    session.delete(obj) #删除行
    
    session.commit()#提交
Screenshot der Operationsergebnisse:

python之SQLAlchemy  ORM示例介绍

6. Erstellen Sie die Hosttabelle hosts und die Gruppierungstabellengruppe , und stellen Sie eine Verbindung her, d. h. eine Gruppe kann mehreren Hosts entsprechen:

Ergebnisse anzeigen:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship

Base = declarative_base()  # 生成一个SqlORM 基类(已经封闭metadata)
#echo=True可以查看创建表的过程
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", echo=True)

class Host(Base):
    __tablename__ = &#39;hosts&#39;   #表名
    id = Column(Integer, primary_key=True, autoincrement=True) #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    #外键关联,主机与组名关联,一个组对应多个主机
    group_id = Column(Integer, ForeignKey("group.id"))


class Group(Base):
    __tablename__ = "group"
    id = Column(Integer,primary_key=True)
    name = Column(String(64), unique=True, nullable=False)


Base.metadata.create_all(engine)  # 创建所有表结构

if __name__ == &#39;__main__&#39;:
    # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
    SessionCls = sessionmaker(bind=engine)
    session = SessionCls()  #连接的实例

    session.commit() #提交

python之SQLAlchemy  ORM示例介绍

Problem: Die Desc-Gruppe wird gefunden, wenn die neu erstellte Gruppentabellenstruktur angezeigt oder aus der Gruppentabelle abgefragt wird. Wenn Sie * aus der Gruppe auswählen, werden Fehler angezeigt!! (Warum dieser Fehler auftritt, kann dies durch eine Beziehung zwischen Gruppe und Datenbank verursacht werden, z von... schätze ich)

Lösung: use desc zcl.group; select * from zcl.group; (zcl ist der Datenbankname)

python之SQLAlchemy  ORM示例介绍

2. Nachdem Sie die Tabelle erstellt haben, müssen Sie sie zur Tabelle „Daten erstellen“ hinzufügen. Erstellen Sie als Nächstes Daten in der Hosts-Tabelle und der Gruppentabelle:

Nach dem Test: Obwohl bei der Ausführung keine Fehler auftreten, ist die Zuordnung nicht erfolgreich, wie unten gezeigt:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker

Base = declarative_base()  # 生成一个SqlORM 基类(已经封闭metadata)
#echo=True可以查看创建表的过程
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", echo=True)

class Host(Base):
    __tablename__ = &#39;hosts&#39;   #表名
    id = Column(Integer, primary_key=True, autoincrement=True) #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    #外键关联,主机与组名关联
    group_id = Column(Integer, ForeignKey("group.id"))


class Group(Base):
    __tablename__ = "group"
    id = Column(Integer,primary_key=True)
    name = Column(String(64), unique=True, nullable=False)

Base.metadata.create_all(engine)  # 创建所有表结构

if __name__ == &#39;__main__&#39;:
    # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
    SessionCls = sessionmaker(bind=engine)
    session = SessionCls()  #连接的实例

    g1 = Group(name = "g1")
    g2 = Group(name = "g2")
    g3 = Group(name = "g3")
    g4 = Group(name = "g4")
    session.add_all([g1,g2,g3,g4])

    #此时上面的g1,g2,g3三条记录还未存在,因为程序运行到这一行时还未commit(),故g1.id也未存在,但是下面一行代码是用到g1.id的!!经过测试: 运行时虽然不曝错,但关联不成功,如下图
    h1 = Host(hostname=&#39;localhost&#39;, ip_addr=&#39;127.0.0.1&#39;,group_id=g1.id)
    session.add(h1)

    session.commit() #提交

python之SQLAlchemy  ORM示例介绍

3. Jetzt tritt das Problem erneut auf. Die Gruppen-ID in der Hosts-Tabelle ist definitiv nicht möglich. Wie kann man nun dafür sorgen, dass „group_id“ nicht leer ist, ohne die Hosts-Tabellendaten zu löschen (z. B. „group_id“ auf 4 setzen und mit „g4“ verknüpfen)? Der folgende Code kann verwendet werden:

g4 = session.query(Group).filter(Group.name=="g4").first()     #找到g4组的对象
h = session.query(Host).filter(Host.hostname=="localhost").update({"group_id":g4.id})  #更新(修改)
session.commit() #提交

4. Frage: Wie bekomme ich die Gruppen-ID mit dem Host verknüpft?

g4=session.query(Group).filter(Group.name=="g4").first()
h=session.query(Host).filter(Host.hostname=="localhost").first()
print("h1:",h.group_id)
Okay, ich Geben Sie zu, dass diese Frage zu einfach ist. Suchen Sie mit dem obigen Code das Hostobjekt h, dann ist h.group_id die Antwort. Die nächste Frage ist der entscheidende Punkt.

5. 此时可以获取已经关联的group_id,但如何获取已关联的组的组名??

print(h.group.name) #AttributeError:&#39;Host&#39;object has no attribute &#39;group&#39;

嗯,你是初学者,你当然会说通过过h.group.name就可以找到与主机关联的组名! BUT,这是不行的,会曝错,因为Host类根本就没有group属性!!

解决方法:

  • first:

from sqlalchemy.orm import relationship       #导入relationship

  • second:

在Host类中加入group = relationship("Group"):

class Host(Base):    __tablename__ = &#39;hosts&#39;   #表名
    id = Column(Integer, primary_key=True, autoincrement=True) #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)    #外键关联,主机与组名关联
    group_id = Column(Integer, ForeignKey("group.id"))    group = relationship("Group")

此时再用print(h.group.name)就不会曝错啦!!

 

6. 哈哈,问题还没完呢。 前面已经实现:通过主机可查看对应组名,那么如何实现通过组名查看对应的主机??

经过前面5个点的历练,你已成为小小的老司机了,于是你很自信地说: 和第5个点一样,在Group类中加入hosts = relationship("Host");

class Host(Base):
    __tablename__ = &#39;hosts&#39;   #表名
    id = Column(Integer,primary_key=True, autoincrement=True)   #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    #外键关联,主机与组名关联
    group_id = Column(Integer,ForeignKey("group.id"))
    group = relationship("Group")

class Group(Base):
    __tablename__ = "group"
    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)
    hosts = relationship("Host")

Base.metadata.create_all(engine)     #创建所有表结构

g4 = session.query(Group).filter(Group.name=="g4").first()
h = session.query(Host).filter(Host.hostname=="localhost").first()
print("h1:",h.group_id)       #h1: 4
#此时可以获取已经关联的group_id,但如何获取已关联的组的组名
print(h.group.name)          #g4
print("g4:",g4.hosts)        #g4:[<__main__.Hostobjectat0x0000000004303860>]

 

7. 通过上面的两句代码可实现双向关联。但必须在两个表都加上一句代码才行,有没有办法只用一句代码就实现双向关联?? 当然有,老司机会这么做: 

在Host类中加入下面这句代码,即可实现双向关联:

group=relationship("Group",backref="host_list")

 

八、合并查询join

合并查询分为: inner join、left outer join、right outer join、full outer join

下面的例子可以让你完全理解join: http://stackoverflow.com/questions/38549/what-is-the-difference-between-inner-join-and-outer-join

python之SQLAlchemy  ORM示例介绍

关于join的原生sql操作:

python之SQLAlchemy  ORM示例介绍

python之SQLAlchemy  ORM示例介绍

 

在SQLAlchemy实现sql.join:

obj = session.query(Host).join(Host.group).all()    #相当于inner join
print("-->obj:",obj)

 

九、分类聚合group by

group by是啥意思呢? 我说下我的理解吧,group即分组,by为通过;合起来即: 通过XX分组;

举个例子吧,现在有两张表,分别是主机表与分组表。两表已经通过group_id建立关联,分组表中有4个数据,分别为g1,g2,g3,g4; id分别为1,2,3,4; 而主机表有3个数据,group_id分别为4,3,4; id分别为1,2,4; 现在对hosts表执行group by命令,进行分类聚合。

具体请看下图:

python之SQLAlchemy  ORM示例介绍

python之SQLAlchemy  ORM示例介绍

对应SQLAlchemy语句:

obj1 = session.query(Host).join(Host.group).group_by(Group.name).all()    #分类聚合
print("-->obj1:",obj1)

 

python之SQLAlchemy  ORM示例介绍

对应SQLAlchemy语句:

obj2 = session.query(Host,func.count(Group.name)).join(Host.group).group_by(Group.name).all()
print("-->obj2:",obj2)

输出:
-->obj2: [(eee7a277edacfa2db32c6af0fb3aa2a9, 1), (f4f7c97c04e3ddaa72fc606608f96c28, 2)]

 

十、多对多关联

多对多关联,即: 一个主机h1可对应在多个组(g1,g2),一个组(g1)可对应多个主机(h1,h2)

想实现如下的多对多关联,需要一张中间表。Eg:
 h1   g1
 h1   g2
 h2   g1

Host表
 h1
 h2
 h3
Group表
 g1 
 g2
 g3

HostToGroup中间表(实现多对多关联,sqlalchemy也是这样实现的)
 id    host_id     group_id  1       1            1
  2       1            2
  3       2            1

虽然有了中间表,但如果想查看一个组对应的所有主机名或者一个主机对应的所有组,还是需要Group/Host与中间表进行一系列的关联操作(join~), 但SqlAlchemy简化了关联操作!!

调用下面命令便会自动关联中间表:

Host.groups()  #查看一个主机对应所有组
Group.hosts()

 

SQLAlchemy是如何实现多对多关联的??

1. 建立中间表,关联其它两个表

from sqlalchemy import create_engine,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship

Base = declarative_base()  # 生成一个SqlORM 基类(已经封闭metadata)
#echo=True可以查看创建表的过程
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", echo=True)


#直接创建表并返回表的实例  Host2Group主动关联Host与Group(被关联)
Host2Group = Table('host_to_group',Base.metadata,
    Column('host_id',ForeignKey('host.id'),primary_key=True),
    Column('group_id',ForeignKey('group.id'),primary_key=True),
    #一个表为什么能创建两个主键(其实是两个列同时作为主键,非空且唯一)
    #PRIMARY KEY (host_id, group_id),
)

2. 在Host表(或Group表)指定中间表的实例,加上backref就不用在Group表中指定

#声明表的映射关系
class Host(Base):
    __tablename__ = 'host'   #表名
    id = Column(Integer, primary_key=True, autoincrement=True) #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    #外键关联,主机与组名关联
    #group_id = Column(Integer, ForeignKey("group.id"))
    groups = relationship("Group",                #关联Group表
                           secondary = Host2Group, #关联第三方表
                           backref = "host_list") #双向关联,不用在Group类中再加这句代码

    def __repr__(self):
        return "f629f4ea386063e8614098b37acef85e" % (self.id,
                                                        self.hostname,
                                                        self.ip_addr)

3. 创建组与主机

if __name__ == '__main__':
    SessionCls = sessionmaker(bind=engine)
    session = SessionCls()
    """
    g1 = Group(name = "g1")
    g2 = Group(name = "g2")
    g3 = Group(name = "g3")
    g4 = Group(name = "g4")
    session.add_all([g1,g2,g3,g4])
    """
    """
    h1 = Host(hostname="h1",ip_addr="10.1.1.1")
    h2 = Host(hostname="h2",ip_addr="10.1.1.2",port=10000)
    h3 = Host(hostname="h3",ip_addr="10.1.1.3",port=6666)
    session.add_all([h1,h2,h3])
    """

4. 建立关联与查询

"""
    groups = session.query(Group).all()
    h1 = session.query(Host).filter(Host.hostname=="h1").first()
    h1.groups = groups    #将h1关联到所有的组
    print("-->:",h1.groups)
    h1.groups.pop()   #删除一个关联
    """
    h2 = session.query(Host).filter(Host.hostname=="h2").first()
    #h2.groups = groups[1:-1]   #将h2关联到组(2和3)
    print("=======>h2.groups:",h2.groups)
    #=======>h2.groups: [6e2fcbe3155f6068e5e0552abc854817,
    #  f1a29f8066407730d73efbdfa1665798]
    #加上__repr__()后,变为=======>h2.groups: [fba807bf0ed0cd82abe904d49adf340d, a9d37a5fcbc886fdd4000cb295264863]

    g1 = session.query(Group).first()
    print("=======>g1:",g1.host_list)
    #=======>g1: [41662fd1e61c9cd77104e8515416c7e0]
    session.commit()

测试截图:

查看表结构:

python之SQLAlchemy  ORM示例介绍

查看表内容:

python之SQLAlchemy  ORM示例介绍

查看第三方表:

python之SQLAlchemy  ORM示例介绍

 

完整例子:

from sqlalchemy import create_engine,func,Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String,ForeignKey
from sqlalchemy.orm import sessionmaker,relationship

Base = declarative_base()  # 生成一个SqlORM 基类(已经封闭metadata)
#echo=True可以查看创建表的过程
engine = create_engine("mysql+pymysql://root:root@localhost:3306/zcl", echo=True)


#直接创建表并返回表的实例  Host2Group主动关联Host与Group(被关联)
Host2Group = Table('host_to_group',Base.metadata,
    Column('host_id',ForeignKey('host.id'),primary_key=True),
    Column('group_id',ForeignKey('group.id'),primary_key=True),
    #一个表为什么能创建两个主键(其实是两个列同时作为主键,非空且唯一)
    #PRIMARY KEY (host_id, group_id),
)


#声明表的映射关系
class Host(Base):
    __tablename__ = 'host'   #表名
    id = Column(Integer, primary_key=True, autoincrement=True) #默认自增
    hostname = Column(String(64), unique=True, nullable=False)
    ip_addr = Column(String(128), unique=True, nullable=False)
    port = Column(Integer, default=22)
    #外键关联,主机与组名关联
    #group_id = Column(Integer, ForeignKey("group.id"))
    groups = relationship("Group",                #关联Group表
                           secondary = Host2Group, #关联第三方表
                           backref = "host_list")#双向关联,不用在Group类中再加这句代码

    def __repr__(self):
        return "f629f4ea386063e8614098b37acef85e" % (self.id,
                                                        self.hostname,
                                                        self.ip_addr)

class Group(Base):
    __tablename__ = "group"
    id = Column(Integer,primary_key=True)
    name = Column(String(64), unique=True, nullable=False)

    def __repr__(self):
        return "5c798f716970eed1a3e59cce8a955665" % (self.id, self.name)


Base.metadata.create_all(engine)  # 创建所有表结构

if __name__ == '__main__':
    SessionCls = sessionmaker(bind=engine)
    session = SessionCls()
    """
    g1 = Group(name = "g1")
    g2 = Group(name = "g2")
    g3 = Group(name = "g3")
    g4 = Group(name = "g4")
    session.add_all([g1,g2,g3,g4])
    """
    """
    h1 = Host(hostname="h1",ip_addr="10.1.1.1")
    h2 = Host(hostname="h2",ip_addr="10.1.1.2",port=10000)
    h3 = Host(hostname="h3",ip_addr="10.1.1.3",port=6666)
    session.add_all([h1,h2,h3])
    """
    """
    groups = session.query(Group).all()
    h1 = session.query(Host).filter(Host.hostname=="h1").first()
    h1.groups = groups  #将h1关联到所有的组
    print("-->:",h1.groups)
    h1.groups.pop()   #删除一个关联
    """
    h2 = session.query(Host).filter(Host.hostname=="h2").first()
    #h2.groups = groups[1:-1]
    print("=======>h2.groups:",h2.groups)
    #=======>h2.groups: [6e2fcbe3155f6068e5e0552abc854817,
    #  f1a29f8066407730d73efbdfa1665798]
    #加上__repr__()后,变为=======>h2.groups: [fba807bf0ed0cd82abe904d49adf340d, a9d37a5fcbc886fdd4000cb295264863]

    g1 = session.query(Group).first()
    print("=======>g1:",g1.host_list)
    #=======>g1: [41662fd1e61c9cd77104e8515416c7e0]
    session.commit()

更多python之SQLAlchemy  ORM示例介绍相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn