關系

實體對象可以和其他實體對象建立關系。一條關系是由關系兩邊的實體對象的兩條屬性定義的:

class Customer(db.Entity):
    orders = Set("Order")

class Order(db.Entity):
    customer = Required(Customer)

在上面的示例中,我們有兩個關系屬性:orderscustomer。當我們定義 Customer 的時候, Orders 還沒有定義,所以需要使用引號將 Orderso 括起來。也可以使用 lambda 表達式:

class Customer(db.Entity):
    orders = Set(lambda: Order)

如果你想要 IDE 幫你檢查實體對象名字的拼寫高亮拼寫錯誤,這種方法很有用。

有一些映射器(例如,django)只需要在一邊定義關系就可以了。Pony 需要在關系的兩邊都明確的定義(就像 Python 之禪說的:明確比暗示好),用戶在每個角度都能看到所有的關系定義。

所有的關系都是雙向的。如果你更新了關系的一邊,另一邊會自動更新。如果我們創建了一個 Orders 的實例,customer 的 orders 集合會更新,添加了這條新的 order。

有三種類型的關系:一對一,一對多,多對多。一對一關系很少使用,大多數關系形式都是一對多和多對多。如果兩個實體對象擁有一對一關系,那基本上就意味著這兩個實體對象可以合並為一個。如果你的數據表中包含很多一對一關系,那就意味著你需要重新思考實體對象的定義了。

一對多關系

這裏有一個一對多關系的例子:

class Order(db.Entity):
    items = Set("OrderItem")

class OrderItem(db.Entity):
    order = Required(Order)

上例中,沒有 order 的情況下就不能建立 OrderItem 的實例,如果我們想建立一個不需要指定 order 的 OrderItem 實例,我們可以指定 order 屬性為 Optional

class Order(db.Entity):
    items = Set("OrderItem")

class OrderItem(db.Entity):
    order = Optional(Order)

多對多關系

為了建立多對多關系,你需要在關系的兩邊都使用 Set 屬性。

class Product(db.Entity):
    tags = Set("Tag")

class Tag(db.Entity):
    products = Set(Product)

為了在數據庫中實現這個關系,Pony 將會創建一個中間表。這是眾所周知的在數據庫中建立多對多關系的方法。

一對一關系

為了建立一對一關系,關系屬性需要設置為 Optional-RequiredOptional-Optional:

class Person(db.Entity):
    passport = Optional("Passport")

class Passport(db.Entity):
    person = Required("Person")

兩個屬性都是 Required 是不允許的,因為這不合理。

自引用

實體對象可以通過自引用建立指向自己的關系。這種關系可以有兩種類型:相稱的和不相稱的。不相稱的關系就是一個實體對象裏的兩個屬性建立的關系。

相稱的關系特殊的地方就是這條關系只有一條屬性,這條屬性定義了關系的兩邊。這種關系可以是一對一也可以是多對多。如下是自引用關系的例子:

class Person(db.Entity):
    name = Required(str)
    spouse = Optional("Person", reverse="spouse") # symmetric one-to-one
    friends = Set("Person", reverse="friends")    # symmetric many-to-many
    manager = Optional("Person", reverse="employees") # one side of non-symmetric
    employees = Set("Person", reverse="manager") # another side of non-symmetric

兩個實體對象間的多種關系

當兩個實體類型之間的關系多於一條的時候,Pony 需要 reverse 屬性來加以區分。這是為了讓 Pony 知道那兩個屬性是一對。像我們考慮一下這個 user 既可以寫微博,又可以給微博點讚的數據表。

class User(db.Entity):
    tweets = Set("Tweet", reverse="author")
    favorites = Set("Tweet", reverse="favorited")

class Tweet(db.Entity):
    author = Required(User, reverse="tweets")
    favorited = Set(User, reverse="favorites")

在上例中,我們必須指定 reverse 屬性。當你嘗試生成映射但是沒有提供reverse 屬性時,你會得到一個異常 pony.orm.core.ERDiagramError: "Ambiguous reverse attribute for Tweet.author"。之所以會這樣是因為 author 屬性在技術角度既可以和 tweets 配對,又可以和 favorites 配對,Pony 沒有足夠的信息區分。

results matching ""

    No results matching ""