SQLAlchemy:是否知道模型对象的字段名称和值? [英] SQLAlchemy: Knowing the field names and values of a model object?

查看:140
本文介绍了SQLAlchemy:是否知道模型对象的字段名称和值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图遵循SOLID面向对象的编程原理,保持DRY等,但是我对Python/SQLAlchemy/Pyramid的新颖性使它变得非常困难.

I'm trying to keep to SOLID object oriented programming principles, stay DRY, etc, but my newness to Python/SQLAlchemy/Pyramid is making it very hard.

我正在尝试将现在知道的用于创建简单Pyramid Framework对象的SQLAlchemy模型用作C#中的反射",在Python中它可能被称为不同的东西(自省?不确定,因为这只是我使用python的第二个星期,但是我在其他语言(C/C ++/C#,Java等)方面有丰富的经验,所以麻烦似乎是将我的知识映射到python的词汇表上,对不起)当我不知道列名称或对象形状的任何形式时,找出数据库表的字段名称,最重要的是,找到当前的字段值.

I'm trying to take what I now know to be a SQLAlchemy model used to create a simple Pyramid Framework object and use what I know to be "reflection" in C#, it may be called something different in Python (Introspection? Not sure as this is only my second week with python but I have lots of experience in other languages (C/C++/C#,Java, etc) so the trouble seems to be mapping my knowledge to the vocabulary of python, sorry), to find out the field names of the database table, and most importantly, the current field values, when I do not know the column names or ANY of the shape of the object in advance.

没错;我不知道'derp'实例有一个名为id或name的字段,只是它在每个字段中都有列和一个值.那就是我所关心的全部.

Thats right; I don't know that the 'derp' instance has a field named id or name, just that it has columns and a value in each of them. And thats all I care about.

目标是能够采用任何SQLAlchemy定义的数据模型,并将其转换为JSON中类型的简单数据类型的column_name-> column_value字段的字典,因为我想最终序列化我在其中创建的任何对象SQLAlchemy传递给json对象,但是只要字典中包含正确的数据类型,我就从那里开始编写字典.手动对每个对象执行此操作违反了太多良好的干净代码规则,并且随着时间的流逝会产生过多的工作.我可以再花一个星期的时间,但是通过正确的方式仍然可以节省时间和精力.

The goal is to be able to take any SQLAlchemy defined data model, and convert it to a dictionary of column_name -> column_value fields of simple data types of the kind found in JSON as I want to ultimately serialize any object I create in SQLAlchemy to a json object, but I will settle for a dictionary as from there its trivial as long as the dictionary holds the correct types of data. Doing this for every object by hand is a violation of too many good clean code rules and will create too much work over time; I could spend another week on this and still save time and effort by doing it the right way.

因此,如果我在SQLAlchemy中将类定义为:

So if I have a class defined in SQLAlchemy as:

class SimpleFooModel(Base):
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    name = Column(VARCHAR(length=12), nullable=False, index=True)

..并且我有一个等于(在python中)的实例:

.. and I have an instance of this equal to (in python):

derp = SimpleFooModel(id=7, name="Foobar")

我只希望能够拥有上述的'derp'实例变量,而又没有关于模型如何成形的其他知识,并且能够将其简化为该简单对象的python key-> value字典,该字典中的每个值都可以使用python syslib中的import json序列化为JSON.

I want to be able to having ONLY the 'derp' instance variable described above, and NO OTHER KNOWLEDGE of how the model is shaped, and be able to flatten it out to a python key->value dictionary for that simple object, where every value in that dictionary can be serialized to JSON using import json from python syslib.

问题是,我已经花了2天的时间来研究此问题,但找不到任何可以在单元测试中获得所需结果的答案; Google一直在这里带我去阅读关于该库的旧版本的老文章,这些老版本要么使用了不再适用的接口,要么接受了实际上根本不起作用的答案;并且由于它们都不是最新的,这确实令我感到惊讶(但是为什么当错误时,Stack Overflow会保留它们并允许Google误导人们却令我感到惊讶)

The problem is , I have been up for 2 days looking at this and I cant find an answer that gives me the results I want in my unit tests ANYWHERE; Google keeps taking me to really old posts here on SO about really old versions of the library that either use interfaces that no longer apply, or have accepted answers that do not actually work at all; and since none of them are recent that does surprise me (but why Stack Overflow keeps them when they are wrong and allows google to mislead people does surprise me)

我知道我可以手动将每个对象的每个对象都连接到json等,但这不仅不美观,而且效率低下,因为当我创建更多对象时,它会为我创造更多的工作,并可能导致重大错误.我想知道如何通过内省/反思来正确地做到这一点,但是似乎没人知道,那些声称在堆栈溢出中给出了所有示例的人实际上根本不起作用(至少在当前情况下如此).事物的版本)

I know I could wire every object manually for every object to json, etc, but thats not only NOT ELEGANT, its inefficient because it just creates more work for me as I create more objects and could lead to big bugs down the road. I want to know how to do this the correct way, with introspection/reflection, but nobody seems to know, and the people who claim to have all given examples here on stack overflow that actually do not work at all (at least with the current versions of things)

对于我来说,这似乎是一个非常常见的用例;并获取列字段列表,然后使用getattr遍历它-就像许多答案说的那样-也不按预期工作;它只是创建看起来像命名空间的样式,它们从不返回列的实际值,并且实际上不存在于任何代码中,因为sqlalchmy创建的字段都不是单例/静态的.

This seems like a really common use case for me; and getting the column field list and then iterating through it with getattr - like many of the answers say to do - doesn't work as expected either; it just creates what look like namespaces that never return the actual value of the column, and don't actually exist in any code as none of the fields created by sqlalchmy are singleton/static.

所以:

    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]

..或者在这种情况下只是给我:

.. or in this case just gives me:

    SimpleFooModel.id
    SimpleFooModel.name

不是我实际在测试中期望的id和name的值分别为7和"Foobar".

NOT the values of 7 and "Foobar" for id and name respectively, that I actually expected in my tests.

实际上,我似乎甚至找不到在对象模型中存储值的位置.否则我可能会蛮力解决这个问题,然后从那里得到它们,这是我会很羞愧地看到的一个丑陋,邪恶的骇客.我通过官方公共api"获得的所有对象似乎都不知道实际数据的存储位置,但是会很高兴地告诉我列名称所使用的路径名称,类型,限制等. ...只是不是我想要的实际数据.

In fact it seems like I cant even find WHERE the values are being stored in the object model; or I could brute force the issue and get them from there as an ugly, evil hack I would be ashamed to look at. All I get through the "official public api" is a lot of objects that seem to have no clue where the real data is being stored, but will happily tell me the name of the path used by the column name and type, restrictions, etc... just not the actual data that I want.

但是,由于我的要求是我不预先知道字段名称,因此无法选择使用对derp.id或derp.name的调用来收集值,因为那样会违反SOLID并迫使我重复进行以下工作:每个班级.所以这不是一个选择.

Yet since my requirement is that I do not know the field names in advance, using a call to derp.id or derp.name to collect the value is not an option since that would violate SOLID and force me to duplicate work for every single class. So its not an option.

也许这是我没有睡两天的事实,但是我很难不将此视为这些库中的严重设计缺陷.我只想将表示表中单行的SQLAlchemy定义的Model对象序列化为python字典,而不必事先知道字段的名称,尽管许多其他语言使此操作变得简单甚至琐碎,但这似乎还很遥远太难了.

Maybe its the fact I have not slept in 2 days but its really hard for me to not see this as a serious design flaw in these libs; I just want to serialize a SQLAlchemy defined Model object representing a single row in a table into a python dictionary without having to know the names of the fields in advance, and while many other languages make this easy or even trivial, this seems to be far too hard than it should be.

有人可以解释一个可行的解决方案,或者为什么我要对我的代码应用SOLID是错误的吗?

Can somebody please explain either a working solution or why I am wrong to want to apply SOLID to my code?

更新了拼写.

推荐答案

使用以下类扩展模型:

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'}对的形式返回字典.

This will do exactly what you want, return a dict in form of {'column_name':'value'} pairs.

这篇关于SQLAlchemy:是否知道模型对象的字段名称和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆