2009-05-29 12 views
27

でスーパーモデルフィールドの冗長な名前をオーバーライドする方法:Fooクラスでのは、私がSuperFooから継承モデルはFooを持っているとしましょうジャンゴ

class SuperFoo(models.Model): 
    name = models.CharField('name of SuperFoo instance', max_length=50) 
    ... 

class Foo(SuperFoo): 
    ... # do something that changes verbose_name of name field of SuperFoo 

、私はのverbose_nameを上書きしたいのですがSuperFooの名前フィールド。私はできますか?そうでない場合は、テンプレートに表示されるように、モデルフォーム定義内にラベルを設定するのが最適なオプションですか?

+0

回答ありがとうございます!したがって、(i)フォーム内にラベルを設定するか、(ii)_meta.get_fieldsメソッドを介してクラスを定義した後にverbose_nameを設定することができます。どちらも実装が簡単ですが、私は_meta.get_fieldsメソッドを使用して、モデルに関連するすべてのものをモデルモジュール内に保持できるようにしたいと思います。 – shanyu

答えて

49

私が使用しているシンプルなハックは以下のとおりです。

class SuperFoo(models.Model): 
    name = models.CharField('name of SuperFoo instance', max_length=50) 
    ... 

class Foo(SuperFoo): 
    ... # do something that changes verbose_name of name field of SuperFoo 
Foo._meta.get_field('name').verbose_name = 'Whatever' 
+3

これは、実際にはSuperFooクラスのフィールドのverbose_nameを変更します。例えば:class Bar(SuperFoo)を持っている場合、Bar._meta.get_field( 'name')で同じ手順を実行しても、 'name'フィールドのverbose_nameは 'Whatever'になります。verbose_name = 'Whatever 2' – mtaube

+2

SuperFooが抽象基本クラスである場合、上記のコメントは当てはまりません。このメソッドは、SuperFooクラスが抽象クラスなので、うまくいきます。class Meta:abstract = True – mtaube

+0

これは本当ですか? – Pureferret

5

あなたの最善の策は、フォーム自体のラベルを設定/変更することです。 Fooモデルのnameフィールドを参照すると(Foo._meta.fieldsで参照するなど)nameフィールドがSuperFooになるため、verbose_nameを変更すると両方のモデルで同じように変更されます。このよう 初期化新しいインスタンスなどの分野での困難につながる 親モデル(指定のフィールドをオーバーライド

また、Fooクラスにnameフィールドを追加すると、どちらかbecauseを動作しません...

Model.__init__にはどのフィールドが初期化されていますか? これらは、通常のPython クラス継承は全く同じようにして を対処する必要はありませんので、Djangoのモデルとの違いは 継承とPythonクラス 継承は単に任意ではない機能です。

5

ジャンゴ-CMSがこれを行い、彼らはCMSPluginから継承モデルでdb_tableフィールドを上書きする方法を見てください。 (私も自分のもののために使用)に煮詰める基礎:あなたはいくつかのチェックを追加することができます

class SuperFooMetaClass(ModelBase): 
    def __new__(cls, name, bases, attrs): 
     new_class = super(SuperFooMetaClass, cls).__new__(cls, name, bases, attrs) 
     new_class._meta.verbose_name = "...." # perhaps only if not customized 
     return new_class 


class SuperFoo(models.Model): 
    __metaclass__ = SuperFooMetaClass 

    .... 

、例えばサブクラス(ダイレクトタイプではない)の更新のみ、または値がカスタマイズされていない場合のみ更新されます。

10

Foo._meta.fieldsを変更するとスーパークラスにも影響するので、スーパークラスが抽象クラスであれば本当に便利です.Gerryが再利用可能なクラスデコレータとして諦めた答えをラップしました:

def modify_fields(**kwargs): 
    def wrap(cls): 
     for field, prop_dict in kwargs.items(): 
      for prop, val in prop_dict.items(): 
       setattr(cls._meta.get_field(field), prop, val) 
     return cls 
    return wrap 

このようにそれを使用してください:上記の例では、継承されたフィールド 'タイムスタンプ' のverbose_nameとhelp_textに変更を

@modify_fields(timestamp={ 
    'verbose_name': 'Available From', 
    'help_text': 'Earliest date you can book this'}) 
class Purchase(BaseOrderItem): 
    pass 

。変更するフィールドがある場合と同じくらい多くのキーワードargを渡すことができます。

+0

ありがとう!これはDjangoを使用して私のために働いた1.8 – pymarco

+0

ありがとう! Django 1.11.4の魅力のように動作しました。 – emi

関連する問題