2016-03-01 178 views
0

例如,使用瓶,SQLAlchemy的和jsontools序列化到JSON像显示-here-,并给予这样的模式:如何在查询之前设置SQLAlchemy ORM类的属性?

class Engine(db.Model): 
    __tablename__ = "engines" 

    id  = db.Column(db.Integer, primary_key=True) 
    this = db.Column(db.String(10)) 
    that = db.Column(db.String(10)) 
    parts = db.relationship("Part") 

    schema = ["id" 
     , "this" 
     , "that" 
     ,  "parts" 
     ] 

    def __json__(self): 
     return self.schema 

class Part(db.Model): 
    __tablename__ = "parts" 

    id   = db.Column(db.Integer, primary_key=True) 
    engine_id = db.Column(db.Integer, db.ForeignKey("engines.id")) 
    code  = db.Column(db.String(10)) 

    def __json__(self): 
     return ["id", "code"] 

如何查询之前改变schema属性,以便它需要对回报的影响数据?

enginelist = db.session.query(Engine).all() 
return enginelist 

到目前为止,我与子类和单表继承成功,像这样:

class Engine_smallschema(Engine): 
    __mapper_args__ = {'polymorphic_identity': 'smallschema'} 

    schema = ["id" 
     , "this" 
     , "that" 
     ] 

enginelist = db.session.query(Engine_smallschema).all() 
return enginelist 

...但它似乎应该有一个更好的办法无需子类化(我不确定这是否明智)。我已经尝试了各种东西,例如设置属性或调用设置内部变量的方法。问题在于,在尝试这样的事情时,查询不喜欢给定的实例对象,并且我不知道SQLAlchemy是否足够好,还不知道是否可以在这些类的预先创建的实例上执行查询。我也可以遍历返回的对象,设置一个新的模式,并得到想要的JSON,但这不是我的解决方案,因为它启动了新的查询(我通常首先请求小数据集)。

还有其他想法吗?

回答

0

JSON序列化发生在烧瓶中,而不是在SQLAlchemy中。因此,__json__函数直到从视图函数返回后才被查询。因此,这与SQLAlchemy无关,而是与自定义编码函数有关,这大概可以改变。

我实际上建议不要试图这样做,如果你有不同的属性想要序列化模型。在影响序列化实例的实例上设置魔术属性违反了最不让人惊讶的原则。相反,例如,您可以创建一个类别为Serializer的类,您可以使用要序列化的字段列表进行初始化,然后将其Engine传递给它以生成可轻松转换为JSON的dict

如果你坚持做你的方式,你可能只是这样做:

for e in enginelist: 
    e.__json__ = lambda: ["id", "this", "that"] 

当然,你可以改变__json__是一个属性,而不是如果你想避免拉姆达。

+0

总的来说,我同意你说的,这就是我问的原因。我曾想过用'__json__'返回的结果影响了SQLAlchemy编写的查询,但我仔细看了看,发现它没有。我只是一个月的时间来学习所有这些(Python,Flask,SQLAlchemy等),并且需要一次性掌握所有内容。因此,我还不知道我使用的序列化程序足以查看如何调整它。我可以切换到像“棉花糖”这样的工具,但是我试图避免大量的DSL(更多的是grok)。你在循环中回应的最后部分是我在问题的最后部分提到的。 – juanitogan

+0

因此,如果可以的话,我最近几天一直在阅读Query API文档,希望能够做到不同的事情。我发现我可以通过'enginelist = db.session.query(Engine).options(noload(Engine.parts))。all()'从大模式中获得“小模式”。这并不符合我原来要求更改JSON返回的原始请求,但我希望它能满足我的需要,以消除不需要它们的较大查询。 – juanitogan

+0

@juanitogan默认情况下,如果您不访问'Engine'实例上的'.parts',SQLAlchemy将不会加载'Engine.parts'。在'Engine'实例上执行'.parts'时,做'noload'只会让SQLAlchemy不返回任何东西。如果你正确地做了序列化,反正''.parts'不会被加载。 – univerio

相关问题