Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Sqlalchemy混合/和事件侦听器_Python_Events_Model_Sqlalchemy - Fatal编程技术网

Python Sqlalchemy混合/和事件侦听器

Python Sqlalchemy混合/和事件侦听器,python,events,model,sqlalchemy,Python,Events,Model,Sqlalchemy,我正在尝试两个新的东西,所以在两个简化和澄清的帮助是感激的 from sqlalchemy.ext.declarative import declared_attr from sqlalchemy import Column, Float, event class TimeStampMixin(object): @declared_attr def __tablename__(cls): return cls.__name__.lower() cre

我正在尝试两个新的东西,所以在两个简化和澄清的帮助是感激的

from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy import Column, Float, event

class TimeStampMixin(object):

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    created = Column(Float)
    modified = Column(Float)
    def __init__(self, created = None,
                       modified = None):
        self.created = created
        self.modified = modified

def create_time(mapper, connection, target):
    target.created = time()

#def modified_time(mapper, connection, target):
#    target.modified = time()

event.listen(TimeStampMixin, 'before_insert', create_time)
#event.listen(TimeStampMixin, 'before_update', modified_time)
所以我想创建一个可以应用于任何类的mixin:

class MyClass(TimeStampMixin, Base):
    etc, etc, etc
此类继承了在创建时创建时间戳和在更新时创建/修改时间戳的功能

导入时出现以下错误:

raise exc.UnmappedClassError(class_)
sqlalchemy.orm.exc.UnmappedClassError: Class 'db.database.TimeStampMixin' is not mapped

aa我在这一点上被难住了。

以下是我在插入事件之前收听
的方法:在
timesmixin
中添加
类方法,该方法注册当前类并处理设置创建时间

例如

这样,您可以:

  • 轻松扩展和更改您收听的内容和注册的内容
  • 重写某些类的create_time方法
  • 明确哪些方法需要设置时间戳
  • 您可以简单地使用它:

    class MyMappedClass(TimeStampMixin, Base):
        pass
    
    MyMappedClass.register()
    

    简单、清晰、无魔力,但仍能像您所希望的那样封装。

    您也可以这样做:

    from sqlalchemy.orm.interfaces import MapperExtension
    
    class BaseExtension(MapperExtension):
        """Base entension class for all entities """
    
        def before_insert(self, mapper, connection, instance):
            """ set the created_at  """
            instance.created = datetime.datetime.now()
    
        def before_update(self, mapper, connection, instance):
            """ set the updated_at  """
            instance.modified = datetime.datetime.now()
    
    
    class TimeStampMixin(object):
        id = Column(Integer, primary_key=True, autoincrement=True)
        created = Column(DateTime())
        modified = Column(DateTime())
    
        __table_args__ = {
            'mysql_engine': 'InnoDB',
            'mysql_charset': 'utf8'
        }
        __mapper_args__ = { 'extension': BaseExtension() }
    
    并将您的类定义为:

    class User(TimeStampMixin, Base):
    

    将侦听器附加到class方法中,它将事件附加到子类

    class TimeStampMixin(object):
        @staticmethod
        def create_time(mapper, connection, target):
            target.created = time()
    
        @classmethod
        def __declare_last__(cls):
            # get called after mappings are completed
            # http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/declarative.html#declare-last
            event.listen(cls, 'before_insert', cls.create_time)
    

    现代SqlAlchemy中最好的方法是使用
    @listens\u for
    装饰器和
    propagate=True

    from datetime import datetime
    from sqlalchemy import Column, Float
    from sqlalchemy.ext.declarative import declared_attr
    from sqlalchemy.event import listens_for
    
    class TimestampMixin():
        @declared_attr
        def created(cls):
            return Column(DateTime(timezone=True))
    
    @listens_for(TimeStampMixin, "init", propagate=True)
    def timestamp_init(target, args, kwargs):
        kwargs["created"] = datetime.utcnow()
    

    你能公布实际的追踪结果吗?另外,您想用这一行完成什么:
    event.listen(TimeStampMixin,'before\u insert',create\u time)
    ?这是行不通的,因为
    TimeStampMixin
    不是SQLAlchemy类(它是object的后代),所以SQLAlchemy无法知道它应该映射到哪个表。该错误是实际回溯的底部。我想要完成的就是我想要完成的,但是现在我又回到了这里,你也指出了,我看到sqlalchemy不会意识到它……但是就像我说的,尝试同时做两件新鲜的事情,我会错过很多。要记住的关键是sqlalchemy中没有什么是真正的魔法,所以,这就是为什么您只需要对它进行具体说明:)@blueblank,如果您感兴趣,
    staticmethod
    只是Python中
    描述符的一个内置示例(这也是处理方法、类方法和属性的方式)。您可以阅读更多信息或看到具体的一个可能的缺点是,
    create\u time
    不能被覆盖。既然
    register
    是一个类方法,那么
    create\u time
    就不能也是一个类方法吗?@mwhite这不是真的。如果在
    MyMappedClass
    上定义
    create\u time
    register()
    将使用它。Classmethod不会有任何不同,它总是绑定到
    register()
    中的一个函数,所以即使是猴子修补类也不会改变它。啊,对了,谢谢。关于
    事件。侦听(…,lambda:cls.create_time)
    呢?无论如何,
    MyMappedClass.create\u time()
    不能调用super()来调用
    TimeStampMixin.create\u time()
    ?我想你可以。为了简单起见,我可能不想在继承方面做太多的工作。但是,是的,那会有用。与前面的答案有什么区别?@SergeBelov使用
    \uuu declare\uu last\uuuu
    ,我想这肯定是一个更好的答案-我不知道
    \uuu declare\u last\uuuuu
    。如果有几个混音使用
    \uuu declare\u last\uuuu
    ,它们会被覆盖吗?如果单个模型包含多个mixin,则不起作用。请注意,MapperExtension自0.7以来一直存在。
    from datetime import datetime
    from sqlalchemy import Column, Float
    from sqlalchemy.ext.declarative import declared_attr
    from sqlalchemy.event import listens_for
    
    class TimestampMixin():
        @declared_attr
        def created(cls):
            return Column(DateTime(timezone=True))
    
    @listens_for(TimeStampMixin, "init", propagate=True)
    def timestamp_init(target, args, kwargs):
        kwargs["created"] = datetime.utcnow()