2013-01-22 4 views
8

Djangoモデルのインスタンスにカスタム属性を追加したいとします。これらの属性は、データベースに格納すべきではありません。他のどのクラスでも、属性は単に__init__メソッドで初期化されます。Djangoモデルでカスタムインスタンス属性を使用する正しい方法は何ですか?

私は既に3つの異なる方法を見ることができますが、どれも完全に満足できるものではありません。それを行うにはより良い/もっとpythonic/djangoistの方法があるのだろうか?

  1. Override__init__方法:構文は少し複雑ですが、それは動作します。

    from django.db.models import Model 
    
    class Foo(Model): 
        def __init__(self, *args, **kwargs): 
        super(Model, self).__init__(*args, **kwargs) 
        self.bar = 1 
    
  2. ジャンゴpost_init信号を使用します。これは非常に読みやすいではないクラス定義の外のクラスコードを取ります。

    from django.dispatch import receiver 
    from django.db.models.signals import post_init 
    @receiver(post_init, sender=Foo) 
        def user_init(sender, instance, *args, **kwargs): 
         instance.bar = 1 
    
  3. 代わりに属性のインスタンスメソッドを使用します。デフォルトの動作は少し不安であるとして育て一般的な例外を持ちます。これらの3つの選択肢、私には少なくとも最悪のような最初のルックス

    class Foo(Model): 
        def bar(self): 
        try: 
         return self.bar 
        except: 
         self.bar = 1 
        return self.bar 
    

。どう思いますか?代わりに?

答えて

3

上書き保存されて__init__は正しい方法です。

7

私はその後、あなただけの代わりに(と機能を呼び出すのプロパティのようにそれにアクセスすることができますpythonで

class Foo(Model): 
    @property 
    def bar(self): 
     if not hasattr(self, '_bar'): 
      self._bar = 1 

     return self._bar 

を利用できるプロパティデコレータを使用します)

あなたも、もう少しまっすぐ前方を得ることができます内蔵フォールバックを有することにより、この、代わりの

​​
+0

興味深いことに、私は@propertyデコレータについて知らなかった。しかし、これはひどく醜いとは思わない? –

+0

コード内のどこにでもgetattrを指定するのではなく、組み込みのデフォルトを設定したい場合はありません。これは単にPythonでアクセサメソッドを作成するための標準的な方法なので、醜い場合はv3の改良版としてGuidoにそれを持たせる必要があります:-P – Bryan

+1

Pythonの2年以上前にこの質問に戻りました私のベルトの下で(2013年!私は若くて無実でした...)。今日私はあなたの答えに行くと思います。 '@property'アプローチは非常にpythonです。一方、djangoモデルのコンストラクタはほとんどオーバーライドされません。 –

関連する問題