zoukankan      html  css  js  c++  java
  • 理解SQLAlchemy的表继承关系(4)--高级应用

    class Entry(AbstractConcreteBase, db.Model):
        """Base Class of Entry."""
     
        id = db.Column(db.Integer, primary_key=True, nullable=False)
        created = db.Column(db.DateTime, nullable=False)
        post_id = declared_attr(lambda c: db.Column(db.ForeignKey("post.id")))
        post = declared_attr(lambda c: db.relationship("Post", lazy="joined"))
     
        @declared_attr
        def __tablename__(cls):
            return cls.__name__.lower()
     
        @declared_attr
        def __mapper_args__(cls):
            # configurate subclasses about concrete table inheritance
            return {'polymorphic_identity': cls.__name__,
                    'concrete': True} if cls.__name__ != "Entry" else {}
     
    class TextEntry(Entry):
        """Text and Article Entry."""
     
        text = db.deferred(db.Column(db.Text, nullable=False))
     
    class PhotoEntry(Entry):
        """Photo Entry."""
     
        path = db.deferred(db.Column(db.String(256), nullable=False))

    以上Entry是一个基类,没有对应的数据库表,TextEntry和PhotoEntry均继承自Entry。

    class Post(db.Model):
        """An Post."""
     
        id = db.Column(db.Integer, primary_key=True, nullable=False)
        description = db.Column(db.Unicode(140), nullable=False)
        entries = db.relationship(Entry, lazy="dynamic")

    以上是我们一个应用示例,Post有一个entries皇粮指向不同的entry,在上述代码中我们直接使用relationship来跟Entry创建一个一对多的关系,

    理想情况应该是post的entries可以包含不同的Entry,如

    >>Post.entries.query.all()
    [<PhotoEntry 'Title' created by tonyseek>,
     <PhotoEntry 'TITLE 2' created by tonyseek>,
     <PhotoEntry 'Title 3' created by tonyseek>,
     <PhotoEntry 'Title 4' created by tonyseek>,
     <TextEntry 'Title' created by tonyseek>]

    但上述代码会出错,出错的原因是因为Entry是一个抽象基类,在数据库中并没有创建对应的数据库表,所以不能创建一对多关系。

    幸运的是AbstractConcreteBase提供了__delcare_last__

    可以用来解决这些问题,代码如下:

    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True, nullable=False)
        description = db.Column(db.Unicode(140), nullable=False)
     
        @classmethod
        def __declare_last__(cls):
            cls.entries = db.relationship(Entry, viewonly=True)
     
        def attach_entries(self, entries):
            """Attach Entries To This Post.
            Example:
                >>> post = Post("An Interesting News", "Wow !!!")
                >>> text_entry = TextEntry(*t_args)
                >>> photo_entry = PhotoEntry(*p_args)
                >>> post.attach_entries([text_entry, photo_entry])
                >>> len(post.entries)
                2
                >>> db.session.commit()
                >>>
            """
            for entry in entries:
                self.entries.append(entry)
                entry.post = self
                db.session.add(entry)
  • 相关阅读:
    梦断代码阅读笔记之一
    市场调研
    站立会议第九天
    站立会议第八天
    站立会议第七天
    站立会议第六天
    站立会议第五天
    团队项目第一阶段冲刺站立会议6(4月23日)
    团队项目第一阶段冲刺站立会议5(4月22日)
    团队项目第一阶段冲刺站立会议4(4月21日)
  • 原文地址:https://www.cnblogs.com/miaoweiye/p/12659536.html
Copyright © 2011-2022 走看看