良い一日!
Djangoドキュメントの モデルセクションの翻訳シリーズの別の部分。
Djangoドキュメントの翻訳:モデル。 パート1
Djangoドキュメントの翻訳:モデル。 パート2
___ メタオプション
___モデルメソッド
_____事前定義済みメソッドのオーバーライド
_____ SQLの使用
___モデルの継承
_____抽象基本クラス
_______ メタ継承
_______ related_namesに注意してください
Djangoドキュメントの翻訳:モデル。 パート4(最後)
メタオプション
Meta内部クラスを使用して、モデルにメタデータを追加できます。
Copy Source | Copy HTML<br/> class Ox (models.Model):<br/> horn_length = models.IntegerField()<br/> <br/> class Meta :<br/> ordering = [ "horn_length" ]<br/> verbose_name_plural = "oxen" <br/>
モデル内のメタデータは「フィールドではないもの」です。たとえば、並べ替えパラメーター( 順序付け )、データベーステーブル名( db_table )、単一( verbose_name )または複数( verbose_name_plural )番号の読み取り可能なオブジェクト名などです。 メタデータはオプションです;モデルへのメタクラスの追加は完全にオプションです。
モデルパラメータのヘルプでメタパラメータの完全なリストを見つけることができます 。
モデルメソッド
モデルにメソッドを定義して、オブジェクトに独自の機能を追加できます。 Managerメソッドはテーブル全体のデータを処理するように設計されていますが、モデルメソッドはモデルの別のインスタンスのアクションに対して作成されます。
この手法は、アプリケーションのビジネスロジックを1つの場所(モデル内)に保存するのに役立ちます。
たとえば、このモデルには独自のメソッドがいくつかあります。
Copy Source | Copy HTML<br/> from django.contrib.localflavor.us.models import USStateField<br/> <br/> class Person (models.Model):<br/> first_name = models.CharField(max_length= 50 )<br/> last_name = models.CharField(max_length= 50 )<br/> birth_date = models.DateField()<br/> address = models.CharField(max_length= 100 )<br/> city = models.CharField(max_length= 50 )<br/> state = USStateField() # Yes, this is America-centric... <br/> <br/> def baby_boomer_status (self):<br/> "Returns the person's baby-boomer status." <br/> import datetime<br/> if datetime .date( 1945 , 8 , 1 ) <= self .birth_date <= datetime .date( 1964 , 12 , 31 ):<br/> return "Baby boomer" <br/> if self .birth_date < datetime .date( 1945 , 8 , 1 ):<br/> return "Pre-boomer" <br/> return "Post-boomer" <br/> <br/> def is_midwestern (self):<br/> "Returns True if this person is from the Midwest." <br/> return self .state in ( 'IL' , 'WI' , 'MI' , 'IN' , 'OH' , 'IA' , 'MO' )<br/> <br/> def _get_full_name (self):<br/> "Returns the person's full name." <br/> return '%s %s' % ( self .first_name, self .last_name)<br/> full_name = property ( _get_full_name ) <br/>
この例の最後のメソッドは、管理属性( プロパティ )です。 詳細はこちら 。
モデルインスタンスのヘルプには、 各モデルに自動的に追加されるメソッドの完全なリストが含まれています 。 それらのほとんどを再定義することができます(以下で詳しく説明します)。 ほとんどの場合、オーバーライドするメソッドもいくつかあります。
__unicode __()
Python言語の「マジックメソッド」。Unicodeでエンコードされたオブジェクトの「表現」を返します。 シンプルでわかりやすい文字列の形式でモデルインスタンスを表示する場合に使用します。 たとえば、対話型コンソールまたは管理インターフェイスで作業する場合。
標準のメソッドはあまり有用ではないため、このメソッドのオーバーライドは非常に頻繁に必要になります。
get_absolute_url()
このメソッドは、DjangoにオブジェクトのURL計算アルゴリズムを伝えます。 特定のオブジェクトのURLを見つける必要があるたびに、管理インターフェイスで使用されます。
一意のURLを持つ各オブジェクトには、このメソッドが含まれている必要があります。
事前定義されたメソッドのオーバーライド
データベースの動作を変更できるモデルメソッドがいくつかあります。 特に、 save()およびdelete()メソッドのアルゴリズムの変更が必要になることがよくあります。
これらのメソッドをオーバーライドして(モデル内の他のすべてのメソッドと同様に)、その動作を変更できます。
たとえば、オブジェクトを保存するときに特定のアクションを実行する場合は、組み込みメソッドのオーバーライドが使用されます( save()メソッドで受け入れられるパラメーターの詳細については、 ドキュメントを参照してください)。
Copy Source | Copy HTML<br/> class Blog (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> tagline = models.TextField()<br/> <br/> def save (self, force_insert=False, force_update=False):<br/> do_something()<br/> super ( Blog , self). save (force_insert, force_update) # The "real" save() method. <br/> do_something_else()
保存を防ぐこともできます:
Copy Source | Copy HTML<br/> class Blog (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> tagline = models.TextField()<br/> <br/> def save (self, force_isert=False, force_update=False):<br/> if self .name == "Yoko Ono's blog" :<br/> return # Yoko shall never have her own blog! <br/> else :<br/> super ( Blog , self). save (force_insert, force_update) # The "real" save() method. <br/>
データがデータベースに保存されるように、継承クラスのメソッド(この例ではsuper(Blog、self).save() )を呼び出すことを忘れないことが重要です。このメソッドの呼び出しを忘れても、データベースは変更されません。
SQLを使用する
別の一般的に使用される手法は、モデルメソッドまたはモジュールメソッドで独自のSQL構造を記述することです。 生のSQLの使用の詳細については、 ドキュメントを参照してください 。
モデルの継承
Djangoバージョン1.0で追加 : リリースノートをお読みください。
Djangoのモデル継承の原理は、Pythonのクラス継承とほぼ同じです。 あなたがしなければならない唯一の決定は、継承されたモデルがデータベーステーブルになるのか、それともデータキーパーのみになるのか、そしてそれらへのアクセスは派生モデルを通してのみ可能になるのかということです。
Djangoには3種類の継承があります。
- 多くの場合、基本クラスには、各派生モデルで定義したくない情報を単に含める必要があります。 このようなクラスは、独立したユニットとして使用されることはありません。つまり、抽象ベースクラス(以下で説明します)が最適です。
- サブクラスを作成するときに、各モデルにデータベース内に独自のテーブルを持たせたい場合は、 マルチテーブル継承に注目してください 。
- 最後に、フィールドを変更せずにPythonレベルでモデルの動作を変更する場合は、 プロキシモデルを使用します 。
抽象基本クラス
抽象基本クラスは、一般的な情報を使用して複数のモデルを作成する場合に役立ちます。 基本クラスを作成し、 metaクラスにabstract = Trueパラメーターを設定すると、データベーステーブルの作成時にこのモデルは使用されません。 代わりに、あるモデルのベースとして使用される場合、そのフィールドは派生クラスに追加されます。 基本クラスと派生クラスのフィールド名が一致する場合、Djangoは例外をスローします。
例:
Copy Source | Copy HTML<br/> class CommonInfo (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> age = models.PositiveIntegerField()<br/> <br/> class Meta :<br/> abstract = True<br/> <br/> class Student ( CommonInfo ):<br/> home_group = models.CharField(max_length= 5 ) <br/>
学生モデルには、 name、age 、 home_groupの 3つのフィールドが含まれます。 CommonInfoモデルは抽象基本クラスであるため、通常のDjangoモデルとしては使用されません。データベーステーブルを生成せず、 managerを持ち、直接保存またはインスタンス化することはできません。
多くの場合、このタイプの継承は要件に適合します。 このメソッドを使用すると、Pythonレベルで一般情報を「ブラケット」できますが、データベースレベルでは、派生クラスごとに個別のテーブルが作成されます。
メタ継承
抽象基本クラスが作成されると、Djangoは、基本クラスで定義した内部Metaクラスを属性として使用できるようにします。 ネイティブクラスMetaが派生クラスで定義されていない場合、親から継承されます。 ただし、必要に応じて、 Metaクラスの継承を使用して基本Metaクラスを拡張できます。 例:
Copy Source | Copy HTML<br/> class CommonInfo (models.Model):<br/> ...<br/> class Meta :<br/> abstract = True<br/> ordering = [ 'name' ]<br/> <br/> class Student ( CommonInfo ):<br/> ...<br/> class Meta ( CommonInfo . Meta ):<br/> db_table = 'student_info' <br/>
Djangoは、抽象基本クラスのMetaクラスに対して1つの調整のみを行います。Meta属性を設定する前に、 抽象パラメーターはFalseに設定されます。 これは、派生クラスが自動的に抽象化されないようにするためです。 もちろん、別の抽象基本クラスを継承する抽象基本クラスを作成できます。 これを行うには、単にabstract = Trueを明示的に設定する必要があります 。
抽象基本クラスのMetaクラスにいくつかの属性を追加しても意味がありません。 たとえば、 db_nameパラメータを追加すると、独自のMetaクラスを持たないすべての派生クラスが同じデータベーステーブルを使用することになります。 ほぼ確実に、これはあなたが望んでいたものではありません。
related_nameに注意してください
ForeignKeyまたはManyToManyFieldフィールドでrelated_name属性を使用する場合、各フィールドに一意の戻り名を定義する必要があります。 これは通常、すべてのフィールドとその値が各派生クラスに追加されるため、抽象基本クラスで問題を引き起こします。
この問題を回避するには、抽象基底クラス(およびそれらのみ)でrelated_name属性を使用する場合、文字列'%(class)s'を名前の一部にする必要があります。 このフィールドが使用される小文字の派生クラスの名前に置き換えられます。 クラスには異なる名前があるため、各属性には一意の値があります。 例:
Copy Source | Copy HTML<br/> class Base (models.Model):<br/> m2m = models.ManyToManyField(OtherModel, related_name= "%(class)s_related" )<br/> <br/> class Meta :<br/> abstract = True<br/> <br/> class ChildA ( Base ):<br/> pass <br/> <br/> class ChildB ( Base ):<br/> pass <br/>
ChildA.m2mの戻り名はchilda_relatedであり、 ChildB.m2mの場合はchildb_relatedになります。 '%(class)s'コンストラクトを使用するのはあなた次第ですが、それを忘れると、Djangoはモデルの検証時(またはsyncdbの実行時)に例外をスローします。
抽象基本クラスのフィールドにrelated_name属性を定義しなかった場合、デフォルトの逆引き名は、派生クラスで直接このフィールドを明示的に定義したかのように、文字列'_set'を追加した小文字の派生クラスの名前になります。 たとえば、上記のテキストでrelated_name属性が省略された場合、m2mフィールドの逆の名前はChildAクラスの場合はchilda_set 、 ChildBクラスの場合はchildb_setになります。
今日はこれですべてです:)次の部分は、このセクションの最後になります。 アンケートを作成するために転送した後、これらの翻訳がhabruに必要かどうかを考えます。 続行するかどうかは、その結果に直接依存します。 それまでの間、開始したものの翻訳を完了する必要があります)
継続する
コメントは大歓迎です:)
Djangoドキュメントの翻訳:モデル。 パート1
Djangoドキュメントの翻訳:モデル。 パート2
Djangoドキュメントの翻訳:モデル。 パート4(最後)