如何定义sqlalchemy的多对多关系

时间:2015-02-03 14:56:17

标签: flask sqlalchemy flask-sqlalchemy

我正在用flask和sqlalchemy写一个项目。

我试图创建一个db,其中Author有很多书。

为此我写道:

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name= db.Column(db.String(80))


class Books(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    author = db.Column(db.Integer, db.ForeignKey('author.id'))

第一个问题:这是正确的方法吗?

第二个问题:我想知道每个作者写的哪些书 - 我怎么能这样做?

第三个问题:让我们说每本书都可以由很多作者撰写,                 我怎么知道哪些作者写了某本书?

我提前感谢

1 个答案:

答案 0 :(得分:2)

  

第一个问题:这是正确的方法吗?

几乎正确。您还应该创建一个存储实际关系的中间模型。由于它是many-to-many relationship,因此需要第三个表来运作。

  

第二个问题:我想知道每个作者写的哪些书 - 我怎么能这样做?

     

第三个问题:让我们说每本书都可以由很多作者撰写,我怎么知道哪些作者写了某本书呢?

您可以使用SQLAlchemy association proxy轻松实现它。

类似的东西:

from myapp import db

from sqlalchemy.ext.associationproxy import association_proxy


class Book(db.Model):
    __tablename__ = 'book'

    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(60))

    # access all authors of that book
    authors = association_proxy('bookauthor', 'author', creator=lambda author: BookAuthor(author=author))

    def __init__(self, title):
        self.title = title

    def __unicode__(self):
        return '<Book {0}>'.format(self.id)


class Author(db.Model):
    __tablename__ = 'author'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))

    # access all books w/ this author
    books = association_proxy('bookauthor', 'book', creator=lambda book: BookAuthor(book=book))

    def __init__(self, name):
        self.name = name

    def __unicode__(self):
        return '<Author {0}>'.format(self.id)


class BookAuthor(db.Model):
    """ This is an association table for the Book<->Author Many to Many relationship. """
    __tablename__ = 'book_author'

    id = db.Column(db.Integer, primary_key=True)

    id_book = db.Column(db.Integer, db.ForeignKey('book.id'), primary_key=True)
    id_author = db.Column(db.Integer, db.ForeignKey('author.id'), primary_key=True)

    # you can also access these objects of books and authors respectively
    book = db.relationship(Book, backref='bookauthor')
    author = db.relationship(Author, backref='bookauthor')

    def __unicode__(self):
        return '<BookAuthor {0}>'.format(self.id)

因此,您将能够使用以下方式访问本书的所有作者:

book = db.session.query(Book).filter_by(title="The Catcher in the Rye")
book.authors()
# [<Author 'J. D. Salinger'>]