2017-08-10 64 views
0

我的问题简而言之:是否可以在SQLAlchemy中访问自定义类型的原始值?如何获取SQLAlchemy自定义类型的原始值?

我实现了自定义类型:

class JSONDocument(TypeDecorator): 
    # override field 
    impl = JSON 

    # Write 
    def process_bind_param(self, value, dialect): 
     if value is not None: 
      req = requests.post(url, data=json.dumps({'data': value})) 
      uri = req.json()['uri'] 
      value = uri 
     return value 

    # Read 
    def process_result_value(self, value, dialect): 
     if value is not None: 
      uri = value 
      req = requests.get(uri) 
      value = req.json()['data'] 
     return value 

我的表模型:

class SomeTable(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    # The column with large json data 
    json_data = db.Column(JSONDocument) 

每当我尝试更新或插入行,这将写入json_data列作为一个结果, SQLAlchemy将调用JSONDocumentprocess_bind_param。然后它会执行一个POST API调用,在我的NoSQL表中创建一个新的数据条目,并将我的SQL表中的json_data列更新为返回的URI。

每当我尝试访问json_data列时,它都会对存储在我的SQL表中的URI执行GET API调用,并返回存储在我的NoSQL表中的实际JSON数据。

我的问题:如何获取存储在JSONDocument所涵盖的SQL表中的URI?我想在更新json_data时对旧的URI执行DELETE API调用。

我试过使用SQLAlchemy的映射事件回调,但我仍然无法获得我的自定义类型后面的URI。

请让我知道,如果我不问清楚我的问题。任何建议或想法表示赞赏。

摘要任务的我试图做的事:

我有一个PostgreSQL数据库(RDS)表中的列:id(INT),json_data(串),other_columns ...

由于json_data列占用太多存储空间,因此我正在将该列中的数据移动到其他NoSQL数据库(DynamoDB)。我实现了一个RESTful API服务器,用于更新,插入和软删除NoSQL表中的数据。

我想实现一个SQLAlchemy自定义类型,当我的应用程序试图访问其他Python代码中的json_data列时,它将自动调用我的API方法。

+0

您的意思是在读取过程中将uri沿着值返回吗? –

+0

不完全,我只想要在正常阅读期间的价值。通过定期阅读,我的意思是像'result = SomeTable.query.first()。json_data'。我问是否有像'result.raw_value'这样的东西,这样我就可以获得自定义类型的URI。 –

+1

如何解决这个问题有很多种方法,但没有“内置”解决方案,因为进程绑定和处理结果都是由您编写的。第一 - 你可以使用“self.uri = value”而不是“uri = value”来代替“req = requests.get(uri)”use“req = requests.get(self.uri)”。这样uri应该可以通过“result.uri”访问。第二个选项是通过session.execute()使用普通SQL。或者甚至你可以创建另一个类,再次从JSONDocument继承,然后再次覆盖process_result_value :) –

回答

1

你有没有关于摆脱自定义TypeDecorator并将你的逻辑移动到SomeTable类似于这个使用属性?

class SomeTable(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    # The column with large json data 
    _uri = db.Column(db.JSON) 

    @property 
    def json_data(self): 
     if self._uri is not None: 
      req = requests.get(self._uri) 
      return req.json()['data'] 
     else: 
      return None 

    @json_data.setter 
    def json_data(self, value): 
     req = requests.post(url, data=json.dumps({'data': value})) 
     self._uri = req.json()['uri'] 

    @property 
    def uri(self): 
     return self._uri 
+0

哇。它使用属性效果非常好!令人惊讶的是,我们用来读写属性和列的代码完全相同(如果这不是真的,请告诉我)。我将不得不做一些单元测试,以确保一切正常。非常感谢你的建议! :) –

+0

我希望一切顺利结束:) –