2017-10-03 11 views
0

私はDjangoにdictを保存したいと思います。 非常に基本的なソリューションは、このようになります:Django - TextFieldからdictを取得

class foo(models.Model): 
    bar = models.TextField() 

fooInstance.bar = json.dumps(my_dict) 

が、私は直接それにアクセスし、常にJSONを使用しないでできるようにしたかったので、私は次のようでした:

class foo(models.Model): 
    _bar = models.TextField() 

    @property 
    def bar(self): 
     import json 
     return json.loads(self._bar) 

    @bar.setter 
    def bar(self, new_bar): 
     import json 
     self._bar = json.dumps(new_bar) 

fooInstance.bar = my_dict 

と、これがために働きますほとんどの場合、私は1つのことをすることができません:

fooInstance.bar['key'] = 'value' 

この表現は、間違いなしです。値は設定されていません。 これはどのように行うことができますか?

何か助けていただければ幸いです。

+2

なぜJSONフィールドを使用しないのですか?多くの実装が利用可能です。 –

+0

https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/fields/#jsonfield –

+0

私はMySQLを使用しているので、postgres固有のフィールドは機能しません。 MySQL用のJSONフィールドはありますか?それで私はdictとしてアクセスできますか? –

答えて

0

barに変更するたびに_barを更新するのではなく、保存する前に_barを変更することもできます。 ここに私の修正です:

class foo(models.Model) 
    _bar = models.TextField() 

     def __getattr__(self, attr): 
      if attr == 'bar': 
       import json 
       try: 
        self.bar = json.loads(self._bar) 
       except ValueError: 
        return {} 
       return self.bar 
      else: 
       return super(foo, self).__getattr__(self, attr) 

     def save(self): 
      import json 
      if hasattr(self, bar): 
       self._bar = json.dumps(self.bar) 
      super(foo, self).save() 

これは動作します。私はfooInstance.barを通常のdictとして扱い、dbに保存することができます。

0

JSONFieldを使用することをお勧めしますが、特定のDBバックエンドを強制しないように質問に答えます。

問題の根本原因は、モデルインスタンスでbarを呼び出すたびに、新しい辞書が作成されて返されるため、変更が失われることです。

この再作成動作を避けるために、作成した辞書をプロパティに保存する必要があります。

class foo(models.Model): 
    _bar = models.TextField() 

    def get_bar(self): 
     dict_value = getattr(self, '_bar_dict', None) 
     if not dict_value: 
      import json 
      dict_value = json.loads(self._bar) 
      setattr(self, '_bar_dict', dict_value) 
     return dict_value 

    def set_bar(self, new_bar): 
     import json 
     self._bar = json.dumps(new_bar) 
     self._bar_dict = dict(new_bar) 

    bar = property(get_bar, set_bar) 

それとも@cached_propertyデコレータを使用することができます。 [12]

+0

私はこれが私の必要とすることをするかどうかはわかりません。問題はfooInstance.save()を実行しても新しい値が保存されないということです。また、セッターは呼び出されていません。私はセッターにprintステートメントを追加しましたが、試してみるとプリントが見えませんでした。 –

+0

@YotamAlonプロパティセッターメソッドのPrintステートメントは抑制されます(つまり、出力は作成されませんが、コードは実行されません)。PRINT STATEMENTSでデバッグすることは絶対に避けてください。コードは正しいです。 –

+0

私はプリントを避けるというパラダイムを理解していますが、実際にはセッターを適切に使用すると(fooInstance.bar = new_bar)、プリントが表示されます。テスト後、これは動作しません。 fooInstance.bar [1] = 2とし、fooInstance.save()は値をdbに保存しません。 –

関連する問題