代码之家  ›  专栏  ›  技术社区  ›  David

当使用sqlalchemy declarative设置不存在的属性时,如何引发错误

  •  0
  • David  · 技术社区  · 7 年前

    使用SQLAlchemy,我发现有时会错误地键入映射到列的属性的名称,这会导致很难捕捉错误:

    class Thing(Base):
        foo = Column(String)
    
    
    thing = Thing()
    thing.bar = "Hello" # a typo, I actually meant thing.foo
    assert thing.bar == "Hello" # works here, as thing.bar is a transient attribute created by the assignment above
    session.add(thing)
    session.commit() # thing.bar is not saved in the database, obviously
    ...
    # much later
    thing = session.query(Thing)...one()
    assert thing.foo == "Hello" # fails
    assert thing.bar == "Hello" # fails, there's no even such attribute
    

    有没有办法配置映射类,以便将未映射到SQLAlchemy列的对象赋值会引发异常?

    0 回复  |  直到 13 年前
        1
  •  3
  •   Daniel Fortunov    10 年前

    好的,解决方案似乎是覆盖 __setattr__ 方法,它允许我们在设置前检查atribute是否已经存在。

    class BaseBase(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 which does not exist in the model.
            We're not checking if the attribute is an SQLAlchemy-mapped column because we also want it to work with properties etc.
            See http://stackoverflow.com/questions/12032260/ for more details.
            """ 
            if name != "_sa_instance_state" and not hasattr(self, name):
                raise AttributeError("Attribute %s is not a mapped column of object %s" % (name, self))
            super(BaseBase, self).__setattr__(name, value)
    
    Base = declarative_base(cls=BaseBase)
    

    有点像炼金术的“严格模式”。。。

        2
  •  0
  •   Community Mohan Dere    9 年前

    覆盖 __get__ 方法,并检查它是否在列中(通过将其与类定义或运行时搜索一起存储)

    更多信息 here 从那时起。