我正在尝试保持SOLID面向对象的编程原则,保持DRY等,但我对Python / SQLAlchemy / Pyramid的新见感正在使它变得非常困难。
我正在尝试将我现在所知道的SQLAlchemy模型用于创建一个简单的Pyramid Framework对象并使用我所知道的C#中的“反射”,它可能在Python中被称为不同的东西(Introspection?不确定,因为这只是我第二周的python,但我有很多其他语言的经验(C / C ++ / C#,Java等)所以麻烦似乎是把我的知识映射到python的词汇表,抱歉),到找出数据库表的字段名,最重要的是当前字段值,当我事先不知道列名或任何形状的对象时。
多数民众赞成;我不知道'derp'实例有一个名为id或name的字段,只是它有每个列中的列和值。这就是我所关心的。
目标是能够获取任何SQLAlchemy定义的数据模型,并将其转换为column_name的字典 - >在JSON中找到的那种简单数据类型的column_value字段,因为我想最终将我在SQLAlchemy中创建的任何对象序列化为json对象,但是只要字典包含正确的类型,我将从那里解决它的简单问题数据的。手动对每个对象执行此操作违反了太多良好的清洁代码规则,并且会随着时间的推移创建太多的工作;我可以在这上花一个星期的时间,但仍然可以通过正确的方式来节省时间和精力。
因此,如果我在SQLAlchemy中定义了一个类:
class SimpleFooModel(Base):
id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
name = Column(VARCHAR(length=12), nullable=False, index=True)
..我有一个等于(在python中)的实例:
derp = SimpleFooModel(id=7, name="Foobar")
我希望能够只拥有上面描述的'derp'实例变量,并且不知道模型是如何形成的,并且能够将其展平为python key->值字典以实现简单对象,其中该字典中的每个值都可以使用python syslib中的import json序列化为JSON。
问题是,我已经看了2天,我找不到一个答案,可以在我的单元测试中得到我想要的结果任何地方;谷歌一直把我带到这里的老帖子,关于那些使用不再适用的接口的图书馆的旧版本,或者已经接受了根本不起作用的答案;并且由于它们中没有一个是最近让我感到惊讶的(但是为什么Stack Overflow在他们出错时保留它们并允许谷歌误导人们确实让我感到惊讶)
我知道我可以手动为每个对象连接每个对象到json等,但这不仅不优雅,效率低,因为它只是为我创造了更多的工作,因为我创造了更多的对象,并可能导致大路上的大错。我想知道如何以正确的方式做到这一点,有内省/反思,但似乎没有人知道,并且声称在堆栈溢出的所有给出示例的人实际上根本不起作用(至少对于当前事物的版本)
这对我来说似乎是一个非常常见的用例;并获取列字段列表,然后使用getattr迭代它 - 就像许多答案所说的那样 - 也不能按预期工作;它只是创建看起来像永远不会返回列的实际值的名称空间,并且实际上不存在于任何代码中,因为sqlalchmy创建的字段都不是单例/静态。
所以:
from sqlalchemy.inspection import inspect
obj = inspect(derp, raiseerr=True)
for key in obj.attrs.keys():
fields[key] = getattr(derp, key)
print fields[key]
请给我:
[Class Name].[Column Name]
..或者在这种情况下只是给了我:
SimpleFooModel.id
SimpleFooModel.name
不分别为id和name的值7和“Foobar”,这是我在测试中实际预期的。
事实上,我似乎无法找到WHERE值存储在对象模型中;或者我可以强行解决这个问题,让他们从那里作为一个丑陋的,邪恶的黑客,我会羞于看。我通过“官方公共API”获得的很多对象似乎都不知道存储真实数据的位置,但很高兴地告诉我列名称和类型,限制等所使用的路径的名称......而不是我想要的实际数据。
然而,由于我的要求是我不提前知道字段名称,使用derp.id或derp.name调用来收集值不是一个选项,因为这会违反SOLID并迫使我重复工作每一堂课。所以它不是一个选择。
也许它是我在2天内没有睡觉的事实,但我真的很难在这些书中看不出这是一个严重的设计缺陷;我只想将表示表中单行的SQLAlchemy定义的Model对象序列化为python字典而不必事先知道字段的名称,而且许多其他语言使这变得容易或甚至是微不足道的,这似乎是远远的太难了。
有人可以解释一个有效的解决方案,或者为什么我想将SOLID应用于我的代码?
编辑:更新拼写。
答案 0 :(得分:4)
使用以下课程扩展您的模型:
class BaseModel(object):
@classmethod
def _get_keys(cls):
return sa.orm.class_mapper(cls).c.keys()
def get_dict(self):
d = {}
for k in self._get_keys():
d[k] = getattr(self, k)
return d
这将完全符合您的要求,以{'column_name':'value'}对的形式返回一个字典。