【问题标题】:Prevent writes to specific tables (read-only tables)防止写入特定表(只读表)
【发布时间】:2013-08-06 05:45:36
【问题描述】:

在使用 Pyramid 和 SQLAlchemy 时,有没有办法将表标记为只读?

一些简短的背景:我正在开发一个具有现有数据库的应用程序,该数据库非常复杂。我的应用程序向该数据库添加了一些新表,但更新(更新、插入、删除)其他表是不安全的,因为该模式没有被很好地理解(并且没有记录)。

我的基本目标是在任何不安全的数据库更新之前快速失败,以便可以找到并删除有问题的代码,因此我和未来的开发人员不会对该应用程序造成任何数据问题。

我的幼稚方法:添加一个 pyramid_tm commit veto 钩子,检查要更新的对象(数据库会话中的新对象、脏对象和删除对象),如果有任何只读表,则否决。

是否有现有的机制来处理这个问题?还是更好的方法?

【问题讨论】:

    标签: sqlalchemy pyramid


    【解决方案1】:

    如果您使用“声明式”方法,您可以尝试将类本身设为“只读”:

    class MyBase(object):
        """
        This class is a superclass of SA-generated Base class,
        which in turn is the superclass of all db-aware classes
        so we can define common functions here
        """
    
        def __setattr__(self, name, value):
            """
            Raise an exception if attempting to assign to an atribute of a "read-only" object
            Transient attributes need to be prefixed with "_t_"
            """
            if (getattr(self, '__read_only__', False)
              and name != "_sa_instance_state"
              and not name.startswith("_t_")):
                raise ValueError("Trying to assign to %s of a read-only object %s" % (name, self))
            super(MyBase, self).__setattr__(name, value)
    
    
    
    Base = declarative_base(cls=MyBase)
    

    同样你可以尝试重写__init__方法来防止对象被实例化。

    但是,在应用程序级别解决这个问题感觉有点脆弱 - 我只想在数据库中创建一个特殊用户供您的应用程序连接,这将节省您想要保持不变的表的有限权限。

    【讨论】:

    • 即使这是一个非常古老的答案,这个概念仍然有效。但是,我需要创建一个自定义 declerative_constructor,而不是覆盖 init 方法。见stackoverflow.com/a/20730249/1211607
    • 我的回答中自定义 --init-- 的目的是在您尝试实例化对象时引发异常,以确保您无法创建该类的新实例并且仅限于到 SqlAlchemy 从查询中返回的那些。
    • 是的,我明白了。但不知何故,如果我在 MyBase.__init__ 方法中实现检查,这在我的情况下不起作用。
    猜你喜欢
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多