hon*_*ane 4 python json sqlalchemy solid-principles pyramid
我正在努力保持面向对象的 SOLID 编程原则,保持 DRY 等,但我对 Python/SQLAlchemy/Pyramid 的陌生使它变得非常困难。
我正在尝试采用我现在知道的用于创建简单 Pyramid Framework 对象的 SQLAlchemy 模型,并使用我所知道的 C# 中的“反射”,它可能在 Python 中被称为不同的东西(内省?不确定,因为这只是我使用 python 的第二周,但我在其他语言(C/C++/C#、Java 等)方面有很多经验,所以麻烦似乎是将我的知识映射到 python 的词汇表,抱歉),以找出数据库表的字段名,最重要的是当前字段值,当我事先不知道列名或任何形状的对象时。
这是正确的; 我不知道 'derp' 实例有一个名为 id 或 name 的字段,只是它在每个字段中都有一个列和一个值。这就是我所关心的。
目标是能够采用任何 SQLAlchemy 定义的数据模型,并将其转换为 column_name -> column_value 字段的字典,这些字段的类型为 JSON 中的简单数据类型,因为我想最终将我在 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)
Run Code Online (Sandbox Code Playgroud)
..我有一个等于(在python中)的实例:
derp = SimpleFooModel(id=7, name="Foobar")
Run Code Online (Sandbox Code Playgroud)
我希望能够只拥有上面描述的“derp”实例变量,而对模型的形状一无所知,并且能够将其展平为该简单对象的 python 键-> 值字典,其中每个可以使用 python syslib 中的 import json 将该字典中的值序列化为 JSON。
问题是,我已经看了 2 天了,但找不到可以在任何地方为我的单元测试提供想要的结果的答案;谷歌一直把我带到 SO 上关于真正旧版本的库的非常旧的帖子,这些版本要么使用不再适用的接口,要么接受了实际上根本不起作用的答案;并且因为它们都不是最近的,这确实让我感到惊讶(但是为什么 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]
Run Code Online (Sandbox Code Playgroud)
只给我:
[Class Name].[Column Name]
Run Code Online (Sandbox Code Playgroud)
.. 或者在这种情况下只给我:
SimpleFooModel.id
SimpleFooModel.name
Run Code Online (Sandbox Code Playgroud)
不是我在测试中实际期望的 7 和“Foobar”分别用于 id 和 name 的值。
事实上,我什至找不到值存储在对象模型中的位置;或者我可以蛮力解决这个问题,然后把它们作为一个丑陋的、邪恶的黑客来解决,我会感到羞耻。我通过“官方公共api”得到的只是很多似乎不知道真实数据存储在哪里的对象,但会很高兴地告诉我列名和类型、限制等使用的路径的名称...只是不是我想要的实际数据。
然而,由于我的要求是我事先不知道字段名称,因此不能使用调用 derp.id 或 derp.name 来收集值,因为这会违反 SOLID 并迫使我为每个类重复工作. 所以它不是一个选择。
也许是因为我已经 2 天没睡觉了,但我真的很难不认为这是这些库中的严重设计缺陷;我只想将表示表中单行的 SQLAlchemy 定义的 Model 对象序列化到 python 字典中,而不必事先知道字段的名称,虽然许多其他语言使这变得简单甚至微不足道,但这似乎很远太难了。
有人可以解释一个有效的解决方案,或者为什么我想将 SOLID 应用于我的代码是错误的?
编辑:更新拼写。
使用以下类扩展您的模型:
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
Run Code Online (Sandbox Code Playgroud)
这将完全符合您的要求,以 {'column_name':'value'} 对的形式返回一个字典。
| 归档时间: |
|
| 查看次数: |
2035 次 |
| 最近记录: |