私は約10モデルの抽象的なモデルを構築しています。どういうわけか、1つのフィールドが抽象モデルで宣言されていないことを確認する必要がありますが、継承モデルで宣言する必要があります。どうやってするか?使用する方法はありますNotImplementedError
か?
2 に答える
Django を深く掘り下げることなく、可能であれば、それを達成する簡単な方法はありません。
主な理由は、DjangoField
では名前の「非表示」が許可されていないためです。これが意味することは、インスタンスである基本抽象クラスで抽象属性を宣言したい場合Field
、通常の Python クラス継承パラダイムとは逆に、子クラスでそれを書き換えることができないということです。ドキュメントから引用するには:
通常の Python クラスの継承では、子クラスが親クラスの属性をオーバーライドすることが許可されています。Django では、これは Field インスタンスである属性には許可されていません (少なくとも現時点では)。基本クラスに author というフィールドがある場合、その基本クラスから継承するクラスに author という別のモデル フィールドを作成することはできません。
親モデルのフィールドをオーバーライドすると、新しいインスタンスの初期化 ( Model. initでどのフィールドを初期化するかを指定する) やシリアル化などの領域で問題が発生します。これらは、通常の Python クラスの継承ではまったく同じ方法で処理する必要がない機能であるため、Django モデルの継承と Python クラスの継承の違いは恣意的なものではありません。
この制限は、Field インスタンスである属性にのみ適用されます。必要に応じて、通常の Python 属性をオーバーライドできます。また、Python が認識する属性の名前にのみ適用されます。データベースの列名を手動で指定している場合は、複数テーブルの継承のために、子モデルと祖先モデルの両方に同じ列名を表示できます (それらは列です)。 2 つの異なるデータベース テーブルで)。
祖先モデルのモデル フィールドをオーバーライドすると、Django は FieldError を発生させます。
ただし、属性がインスタンスでない場合 (ほとんどありませんが)、 decoratorField
を使用することで目的を正確に達成できます。@property
このようなものが動作するはずです:
class Person(models.Model):
def __init__(self, *args, **kwargs):
super(Person, self).__init__(*args, **kwargs)
self.last_name
first_name = models.CharField(max_length=30)
@property
def last_name(self):
raise NotImplementedError
class Meta:
abstract = True
class Student(Person):
home_group = models.CharField(max_length=5)
last_name = "Doe" # "models.CharField()" will not work!
class BadStudent(Person):
home_group = models.CharField(max_length=5)
# "NotImplmentedError" will be raised when instantiating BadStudent()
も参照してくださいabc.abstractproperty
。ただし、Django のモデル継承でどのように機能するかはわかりません。
なんでやりたいの??AbstractModel で共通フィールドを宣言できない理由はどれですか??
本当にやりたい場合は、次の手順を使用してください: スーパー クラス コンストラクター内のサブクラスにメソッドを追加する