Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/363.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 从非orm类继承SQLAlchemy_Python_Inheritance_Orm_Sqlalchemy_Ruamel.yaml - Fatal编程技术网

Python 从非orm类继承SQLAlchemy

Python 从非orm类继承SQLAlchemy,python,inheritance,orm,sqlalchemy,ruamel.yaml,Python,Inheritance,Orm,Sqlalchemy,Ruamel.yaml,我正在尝试开发非ORM类的ORM版本,以便能够将对象存储在数据库中(如果可能的话,还可以检索回来) 我现在想要实现的是一个类似的对象,它的行为类似于Python世界中的User,但也可以用作ORM对象,因此可以将其存储在数据库中。我巧妙地尝试的是: Base = declarative_base() class SQLUser(Base, User): id = Column(Integer, primary_key=True) name = Column(String)

我正在尝试开发非ORM类的ORM版本,以便能够将对象存储在数据库中(如果可能的话,还可以检索回来)

我现在想要实现的是一个类似的对象,它的行为类似于Python世界中的
User
,但也可以用作ORM对象,因此可以将其存储在数据库中。我巧妙地尝试的是:

Base = declarative_base()

class SQLUser(Base, User):

    id = Column(Integer, primary_key=True)
    name = Column(String)
    age = Column(Integer)

    def __init__(self, name, age):
        self.name = name
        self.age = age
在Python 2上运行具有此类层次结构的示例会产生以下错误:

类型错误:调用元类基时出错 元类冲突:派生类的元类必须是其所有基元类的(非严格)子类

我相信这与
YAMLObject
元类有关。。。但是我需要它,因为我希望能够将这些对象保存为YAML。对于我读到的关于这个错误的内容,我可能应该使用第三个元类,该元类继承自
YAMLObject
元类和
Base
,然后使用它创建我想要的类

class MetaMixinUser(type(User), type(Base)):
    pass

class SQLUser(six.with_metaclass(MetaMixinUser)):
    #[...]
不幸的是,这会产生另一个错误:

AttributeError:类型对象“SQLUser”没有属性“\u decl\u class\u registry”


您能告诉我我的推理哪里有缺陷吗?

如果您赶时间:从
ruamel.yaml
0.15.19开始,您可以只使用一条语句,而无需对
yamobject
进行子类化:

yaml = ruamel.yaml.YAML()
yaml.register_class(User)
import sys
import ruamel.yaml
from ruamel.std.pathlib import Path

yaml = ruamel.yaml.YAML(typ='unsafe')

class User(ruamel.yaml.YAMLObject):
    yaml_tag = u'user'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(cls.yaml_tag, 
                                            u'{.name}-{.age}'.format(node, node))

    @classmethod
    def from_yaml(cls, constructor, node):
        # type: (Any, Any) -> Any
        return User(*node.value.split('-'))


data = {'users': [User('Anthon', 18)]}
yaml.dump(data, sys.stdout)
print()
tmp_file = Path('tmp.yaml')
yaml.dump(data, tmp_file)
rd = yaml.load(tmp_file)
print(rd['users'][0].name, rd['users'][0].age)

YAMLObject
是为了向后兼容PyYAML而存在的,尽管它可能很方便,但我并不推荐使用它,原因有三:

  • 它使您的类层次结构依赖于
    YAMLObject
    ,正如您所注意到的,这可能会干扰其他依赖关系
  • 默认情况下,它使用不安全的
    加载程序
  • 基于Python装饰器的解决方案将同样方便,并且侵入性更小
  • 子类化
    YAMLObject
    所做的唯一真正的事情是为该
    yaml_标记注册一个
    构造函数
    ,为子类注册一个
    representer

    如果运行Python2,所有示例都假定来自_ufuture _uu import print_函数的

    根据子类化
    YAMLObject
    ,如果您有以下内容:

    yaml = ruamel.yaml.YAML()
    yaml.register_class(User)
    
    import sys
    import ruamel.yaml
    from ruamel.std.pathlib import Path
    
    yaml = ruamel.yaml.YAML(typ='unsafe')
    
    class User(ruamel.yaml.YAMLObject):
        yaml_tag = u'user'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @classmethod
        def to_yaml(cls, representer, node):
            return representer.represent_scalar(cls.yaml_tag, 
                                                u'{.name}-{.age}'.format(node, node))
    
        @classmethod
        def from_yaml(cls, constructor, node):
            # type: (Any, Any) -> Any
            return User(*node.value.split('-'))
    
    
    data = {'users': [User('Anthon', 18)]}
    yaml.dump(data, sys.stdout)
    print()
    tmp_file = Path('tmp.yaml')
    yaml.dump(data, tmp_file)
    rd = yaml.load(tmp_file)
    print(rd['users'][0].name, rd['users'][0].age)
    
    这将使你:

    users: [!<user> Anthon-18]
    
    Anthon 18
    
    上面使用的是
    SafeLoader
    (和
    SafeDumper
    ),这是朝着正确方向迈出的一步。但是,如果您有很多类,那么添加上面的
    XXXX.add_YYY
    行会很麻烦,因为这些条目几乎相同,但并不完全相同。而且它不会处理缺少到\u yaml
    和来自\u yaml
    的类

    为了解决上述问题,我建议您在文件
    myyaml.py
    中创建一个decorator
    yaml\u对象和一个helper类:

    import ruamel.yaml
    
    yaml = ruamel.yaml.YAML(typ='safe')
    
    class SafeYAMLObject(object):
        def __init__(self, cls):
            self._cls = cls
    
        def to_yaml(self, representer, data):
            return representer.represent_yaml_object(
                self._cls.yaml_tag, data, self._cls,
                flow_style=representer.default_flow_style)
    
        def from_yaml(self, constructor, node):
            return constructor.construct_yaml_object(node, self._cls)
    
    def yaml_object(cls):
        yaml.representer.add_representer(
            cls, getattr(cls, 'to_yaml', SafeYAMLObject(cls).to_yaml))
        yaml.constructor.add_constructor(
            cls.yaml_tag, getattr(cls, 'from_yaml', SafeYAMLObject(cls).from_yaml))
        return cls
    
    有了这些,你可以:

    import sys
    from ruamel.std.pathlib import Path
    from myyaml import yaml, yaml_object
    
    @yaml_object
    class User(object):
        yaml_tag = u'user'
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @classmethod
        def to_yaml(cls, representer, node):
            return representer.represent_scalar(cls.yaml_tag, 
                                                u'{.name}-{.age}'.format(node, node))
    
        @classmethod
        def from_yaml(cls, constructor, node):
            # type: (Any, Any) -> Any
            return User(*node.value.split('-'))
    
    
    data = {'users': [User('Anthon', 18)]}
    
    yaml.dump(data, sys.stdout)
    print()
    tmp_file = Path('tmp.yaml')
    yaml.dump(data, tmp_file)
    rd = yaml.load(tmp_file)
    print(rd['users'][0].name, rd['users'][0].age)
    
    同样的结果。如果从_yaml
    方法中删除
    到_yaml
    ,则会得到相同的最终值,但yaml略有不同:

    users:
    - !<user> {age: 18, name: Anthon}
    
    Anthon 18
    

    ⑨ 免责声明:我是本回答中使用的
    ruamel.yaml
    包的作者。

    免责声明2:我并不是真正的18岁,但我确实遵循了布莱恩·亚当斯(Brian Adams)在专辑标题歌中表达的观点

    你不必继承自
    YAMLObject
    就可以转储
    用户
    。子类化是实现转储和加载的最具侵入性的方式。您的
    User
    类可能无法工作,因为它没有
    yaml\u标记。您是否愿意删除对
    YAMLObject
    的依赖关系?@Anthon抱歉,我省略了
    yaml\u标记,但它就在那里。我编辑了我的问题。
    User
    类本身工作正常(我实现了
    to_yaml
    方法,使类能够正确地转储到yaml文件中)。我对一切都是开放的,但通过这种方式,我可以以透明的方式将对象转储给最终用户。只需一个
    yaml.dump
    就可以像预期的那样工作……我补充道。我不确定您在回答中实际使用了哪些解决方案,但注册应该对您有效,装饰可能仍然会干扰您,因为它具有包装功能。@Anthon我按照您的建议使用了装饰器,并且在我做的简短测试中,继承按预期工作。谢谢你的帮助和支持!
    class SQLUser(Base, User):