简体   繁体   English

与Django contenttypes中的sqlalchemy的通用关系

[英]Generic relation with sqlalchemy as in django contenttypes

I'm trying to make some generic apps using Sql Alchemy, such as tags or rating for any model. 我正在尝试使用Sql Alchemy制作一些通用应用程序,例如任何模型的标签或评级。 But I couldn't find any help in the docs. 但是我在文档中找不到任何帮助。 I really liked what I could do with the django contenttypes framework ? 我真的很喜欢django contenttypes框架可以做什么? Is there any similar functionality in Sql Alchemy ? Sql Alchemy中有任何类似的功能吗?

I once wrote some example code about something similar to this (see http://taketwoprogramming.blogspot.com/2009/08/reusable-sqlalchemy-models.html ). 我曾经写过一些与此类似的示例代码(请参阅http://taketwoprogramming.blogspot.com/2009/08/reusable-sqlalchemy-models.html )。

The basic idea is that you can create a model like this: 基本思想是可以创建如下模型:

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

...where commentable is defined like this... ...其中可注释的定义是这样的...

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

Basically, the commentable decorator dynamically creates a new type and table, along with some helper methods to the decorated class. 基本上,可注释装饰器动态创建一个新的类型和表,以及装饰类的一些帮助器方法。 This is the test I used to test that the code works, which shows some example of how it would work... 这是我用来测试代码是否正常工作的测试,其中显示了一些示例代码如何工作...

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)

I wrote this awhile ago, but I don't think there's anything in SQLA that will do this kind of thing for you, but you can create something similar without too much trouble. 我之前写过这篇文章,但是我认为SQLA中没有什么可以为您做这种事情,但是您可以创建类似的东西而不会带来太多麻烦。 In my example, I created new mapped classes and methods to use it on the fly in a class decorator. 在我的示例中,我创建了新的映射类和方法以在类装饰器中即时使用它。

I never really made much use out of it, but it might give you some ideas. 我从来没有真正使用它,但是它可能会给您一些想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM