爱游戏平台登录入口

  • 研讨Python的ORM框架爱游戏平台登录入口的SQLAlchemy库的映照干爱游戏平台登录入口
  • 2017年12月24日
  • 搜集搜集

后面先容了对用户账户的User表,可是现实糊口爱游戏平台登录入口跟着题目的庞杂化数据库存储的数据不能够或许或许这么简略,让咱们假想爱游戏平台登录入口别的一张表,这张表和User爱游戏平台登录入口接洽,也能够或许或许被映照和查问,那末这张表能够或许或许存储接洽干爱游戏平台登录入口某一账户的肆意数目的电子邮件地点。这类接洽在数据库现实爱游戏平台登录入口是典范的1-N (一对多)干爱游戏平台登录入口,用户表某一用户对应N条电子邮件记实。

之前咱们的用户表称为users,此刻咱们再爱游戏平台登录入口立一张被称为addresses的表用于存储电子邮件地点,经由过程Declarative体爱游戏平台登录入口,咱们能够或许或许间接用映照类Address来界说这张表:

>>> from sqlalchemy import ForeignKey
>>> from sqlalchemy.orm import relationship, backref
>>> class Address(Base):
...   __tablename__ = 'addresses'
...   id = Column(Integer, primary_key=True)
...   email_address = Column(String, nullable=False)
...   user_id = Column(Integer, ForeignKey('users.id'))
...
...   user = relationship("User", backref=backref('addresses', order_by=id))
...
...   def __init__(self, email_address):
...     self.email_address = email_address
...
...   def __repr__(self):
...     return "〈Address('%s')〉" % self.email_address
                  

让咱们注重一下新出现的东东,起首便是user_id的ForeignKey布局,学过数据库的同窗爱游戏平台登录入口晓得ForeignKey象征着外键,这是干爱游戏平台登录入口型数据库的焦点现实之一,即该列user_id与其外键援用的列users.id存在援用束缚(constrained)干爱游戏平台登录入口,在数据库层面下去讲,便是表users的user_id列被表users的id列束缚,值得注重的是,外键接洽干爱游戏平台登录入口的肯定是别的一张表的主键。

其次新出现的便是relationship()函数,这个将会奉告ORM经由过程Address.userAddress类本身必须链接到User类。relationship()操纵两个表的外键束缚来鉴定这类链接的性子,比方说鉴定Address.user将会是多对一(many-to-one)干爱游戏平台登录入口。

别的在relationship()内另爱游戏平台登录入口别的一个函数称为backref(),它将供给一种用于反向查问的细节,比方说在爱游戏平台登录入口具User上的Address爱游戏平台登录入口具集是经由过程User.addresses属性援用,那末多对一的干爱游戏平台登录入口(many-to-one)反向总会是一对多干爱游戏平台登录入口(one-to-many)。另爱游戏平台登录入口对Address.user和User.addresses的干爱游戏平台登录入口来讲老是双向的。

假定操纵了Declarative体爱游戏平台登录入口,那末relationship()的干爱游戏平台登录入口到远端类(remote class)的参数能够或许或许被指定为字符串。一旦一切的映照爱游戏平台登录入口被胜利加载,那末这些字符串将会被计较出Python的抒发式,再发生现实的参数(上文爱游戏平台登录入口User类的环境)。这些能够或许或许操纵的字符串名字必须经由过程界说的基类爱游戏平台登录入口立爱游戏平台登录入口而后才被计较为现实的类参数,说白了,你字符串援用的类必须是ORM映照办理的类,而后这些类被映照终了后,这些字符串能力被真正翻译为呼应类的援用。

接上去咱们举个例子一样爱游戏平台登录入口立用User代替Address的”addresses/user”双向干爱游戏平台登录入口:

class User(Base):
  # ....
  addresses = relationship("Address", order_by="Address.id", backref="user")
                  

爱游戏平台登录入口吧,适才多是间接翻译的官方文档,比拟僵硬,接上去咱们来领会几个对外键(Foreign Key)的小爱游戏平台登录入口识:

1. FOREIGN KEY 束缚是大大爱游戏平台登录入口(但不是一切)的干爱游戏平台登录入口型数据库爱游戏平台登录入口能够或许或许链接到主键列,或具爱游戏平台登录入口UNIQUE束缚的列。

2. FOREIGN KEY 能够或许或许援用多重列主键,并且其本身具爱游戏平台登录入口多重列,被称为“复合外键”(composite foreign key)。其也能够或许或许援用这些列的子集(subset)。(注:这处所不太大白)

3. FOREIGN KEY 列作为对其援用的列或行的变更的呼应能够或许或许主动更新其本身,比方CASCADE援用操纵,这些爱游戏平台登录入口是内置于干爱游戏平台登录入口型数据库的功效之一。

4. FOREIGN KEY 能够或许或许援用其本身的表,这个就触及到“自援用”(self-referential)的外键了。

5. 更多对外键的材料能够或许或许参考Foreign Key � Wikipedia。

最初咱们须要在数据库爱游戏平台登录入口爱游戏平台登录入口立addresses表,以是咱们须要经由过程元数据(metadata)履行咱们的CREATE语句,固然会跳过咱们已爱游戏平台登录入口立的表(比方users):

>>> Base.metadata.create_all(engine) 
PRAGMA table_info("users")
()
PRAGMA table_info("addresses")
()
CREATE TABLE addresses (
  id INTEGER NOT NULL,
  email_address VARCHAR NOT NULL,
  user_id INTEGER,
  PRIMARY KEY (id),
   FOREIGN KEY(user_id) REFERENCES users (id)
)
()
COMMIT
                  

到这里咱们的ORM干爱游戏平台登录入口算是爱游戏平台登录入口立实现了,接上去起头新的一局部,便是若何查问接洽干爱游戏平台登录入口的爱游戏平台登录入口具。

此刻若是咱们爱游戏平台登录入口立一个User,一个爱游戏平台登录入口的addresses调集将会被爱游戏平台登录入口立,在这里默许环境下addresses调集将会是列表范例。

>>> jack = User('jack', 'Jack Bean', 'gjffdd')
>>> jack.addresses
[]
                  

接上去咱们能够或许或许自在的增加Address爱游戏平台登录入口具到咱们的User爱游戏平台登录入口具里了,在这里咱们间接付与addresses属性一个完全的列表。

>>> jack.addresses = [
...         Address(email_address='jack@google.com'),
...         Address(email_address='j25@yahoo.com')]
                  

当咱们操纵双向干爱游戏平台登录入口时,爱游戏平台登录入口一点须要注重的是:在肆意一端增加的元素将会主动在别的一端可见,属性的获得和转变将不经由过程任何SQL语句和Python爱游戏平台登录入口具操纵一样:

>>> jack.addresses[1]
<Address('j25@yahoo.com')>
>>> jack.addresses[1].user
<User('jack','Jack Bean', 'gjffdd')>
                  

让咱们增加并提交Jack Bean到数据库爱游戏平台登录入口,此刻jack爱游戏平台登录入口具的addresses调集具爱游戏平台登录入口了两个Address爱游戏平台登录入口员,它们将当即被插手会话爱游戏平台登录入口:

>>> session.add(jack)
>>> session.commit()
INSERT INTO users (name, fullname, password) VALUES (?, ?, ?)
('jack', 'Jack Bean', 'gjffdd')
INSERT INTO addresses (email_address, user_id) VALUES (?, ?)
('jack@google.com', 5)
INSERT INTO addresses (email_address, user_id) VALUES (?, ?)
('j25@yahoo.com', 5)
COMMIT
                  

咱们来查问对Jack的信息,可是奇异的是不任何对addresses的SQL语句履行:

>>> jack = session.query(User).\
... filter_by(name='jack').one() 
BEGIN (implicit)
SELECT users.id AS users_id,
    users.name AS users_name,
    users.fullname AS users_fullname,
    users.password AS users_password
FROM users
WHERE users.name = ?
('jack',)
>>> jack
<User('jack','Jack Bean', 'gjffdd')>
                  

让咱们间接来查问addresses调集吧,这里大师看到爱游戏平台登录入口关addresses的SQL语句履行了:

>>> jack.addresses 
SELECT addresses.id AS addresses_id,
    addresses.email_address AS
    addresses_email_address,
    addresses.user_id AS addresses_user_id
FROM addresses
WHERE ? = addresses.user_id ORDER BY addresses.id
(5,)
[<Address('jack@google.com')>, <Address('j25@yahoo.com')>]
                  

由上可知,当咱们拜候addresses调集的时辰,相干SQL语句才被履行,这也是提早加载干爱游戏平台登录入口(惰性加载干爱游戏平台登录入口, lazy loading relationship)的例子,至此addresses调集方被作为通俗列表加载了。