【问题标题】:Generic relation with sqlalchemy as in django contenttypes与 django contenttypes 中的 sqlalchemy 的一般关系
【发布时间】:2011-07-20 03:36:07
【问题描述】:

我正在尝试使用 Sql Alchemy 制作一些通用应用程序,例如任何模型的标签或评级。但我在文档中找不到任何帮助。我真的很喜欢我可以用 django contenttypes 框架做些什么? Sql Alchemy 中是否有类似的功能?

【问题讨论】:

    标签: python django sqlalchemy flask


    【解决方案1】:

    我曾经写过一些与此类似的示例代码(请参阅http://taketwoprogramming.blogspot.com/2009/08/reusable-sqlalchemy-models.html)。

    基本思想是你可以像这样创建一个模型:

    @commentable
    class Post(Base):
        __tablename__ = 'posts'
        id = sa.Column(sa.Integer, primary_key=True)
        text = sa.Column(sa.String)
    

    ...commentable 是这样定义的...

    class BaseComment(object):
        pass
    
    def build_comment_model(clazz):
        class_table_name = str(class_mapper(clazz).local_table)
        metadata = clazz.metadata
    
        comment_class_name = clazz.__name__ + 'Comment'
        comment_class = type(comment_class_name, (BaseComment,), {}) 
    
        comment_table_name = class_table_name + '_comments'
        comment_table = sa.Table(comment_table_name, metadata,
            sa.Column('id', sa.Integer, primary_key=True),
            sa.Column(class_table_name + '_id',
                sa.Integer,
                sa.ForeignKey(class_table_name + '.id')),
    
            sa.Column('text', sa.String),
            sa.Column('name', sa.String(100)),
            sa.Column('url', sa.String(255)),
        )   
    
        mapper(comment_class, comment_table)
    
        return comment_class, comment_table
    
    def commentable(clazz):
        comment_class, comment_table = build_comment_model(clazz)
    
        clazz.Comment = comment_class
        setattr(clazz, 'comments', relation(comment_class))
    
        def add_comment(self, comment):
            self.comments.append(comment)
    
        setattr(clazz, 'add_comment', add_comment)
    
        return clazz
    

    基本上,commentable 装饰器会动态创建一个新类型和表,以及被装饰类的一些辅助方法。这是我用来测试代码是否有效的测试,它展示了它如何工作的一些示例......

    class TestModels(SATestCase):
        def test_make_comment(self):
            p = Post()
            p.text = 'SQLAlchemy is amazing!'
    
            text = 'I agree!'
            name = 'Mark'
            url = 'http://www.sqlalchemy.org/'
    
            c = Post.Comment()
            c.text = text
            c.name = name
            c.url = url 
            p.add_comment(c)
            Session.add(p)
    
            # This is a method I use to force the reload of the objects from
            # the database to make sure that when I test them, I'm actually
            # pulling from the database rather than just getting the data
            # of the object still in the session.
            p = self.reload(p)
    
            self.assertEquals(len(p.comments), 1)
            c = p.comments[0]
            self.assertEquals(c.text, text)
            self.assertEquals(c.name, name)
            self.assertEquals(c.url, url)
    

    我不久前写过这个,但我认为 SQLA 中没有任何东西可以为你做这种事情,但你可以创建类似的东西而不会太麻烦。在我的示例中,我创建了新的映射类和方法,以便在类装饰器中动态使用它。

    我从来没有真正用过它,但它可能会给你一些想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 2015-12-10
      • 1970-01-01
      相关资源
      最近更新 更多