2

ここで疑問があります...

3 つのクラスがあるとします。

class CarSpec(models.Model):
    x = models.IntegerField(default=20)
    y = models.CharField(max_length=100, blank=True)
    z = models.CharField(max_length=50, blank=True)
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'A'})
    car_brand = models.CharField(max_length=100, blank=True)
    car_model = models.CharField(max_length=50, blank=True)
    number_of_doors = models.IntegerField(default=2)

class MotoSpec(models.Model):
    x = models.IntegerField(default=20)
    y = models.CharField(max_length=100, blank=True)
    z = models.CharField(max_length=50, blank=True)
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'C'})
    motor_brand = models.CharField(max_length=100, blank=True)
    motor_model = models.CharField(max_length=50, blank=True)
    powered_weels = models.IntegerField(default=1)

class Chassis(models.Model):
    name = models.CharField(max_length=50, blank=False)
    type = models.CharField(max_length=2, choices = GAME_TYPES, default="A")

GAME_TYPES = (('A', 'Car'),('B', 'Truck'),('C', 'Motorcycle'))

私はこの 3 つのクラスで作業していましたが、私のアプリでは、それぞれの状況にいくつかのビジネス ルールを適用するために、シャーシの種類を常に確認する必要がありました...これは正しいアプローチではないと思ったので、計画しました.これ:

class Spec(models.Model):
    x = models.IntegerField(default=20)
    y = models.CharField(max_length=100, blank=True)
    z = models.CharField(max_length=50, blank=True)

    class Meta:
        abstract = True

2 つのサブクラスがあります。

class CarSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'A'})
    car_brand = models.CharField(max_length=100, blank=True)
    car_model = models.CharField(max_length=50, blank=True)
    number_of_doors = models.IntegerField(default=2)

class MotoSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'C'})
    motor_brand = models.CharField(max_length=100, blank=True)
    motor_model = models.CharField(max_length=50, blank=True)
    powered_weels = models.IntegerField(default=1)

class Chassis(models.Model):
    name = models.CharField(max_length=50, blank=False)
    type = models.CharField(max_length=2, choices = GAME_TYPES, default="A")

GAME_TYPES = (('A', 'Car'),('B', 'Truck'),('C', 'Motorcycle'))

わかりました、ここまではすべて大丈夫です。以前のクラスで動作していたアプリで何も変更されず、すべてのオブジェクトが期待どおりにデータベースに保持されていました..

しかし、私の問題は残ります..私は引き続き CarSpec と MotoSpec をインスタンス化し、Spec ではありません...しかし... クラスを拡張する代わりに常に Spec を使用したいのですが...そのためにはどうすればよいですか?その (または他の) メソッドから CarSpec または MotoSpec を取得するために、Chassis を彼のinitメソッドに渡す Spec オブジェクトをインスタンス化することができます..

EDITED-IMPORTANT:2つのスペックのそれぞれに特定のフィールドがあるため、MotoSpecのpowered_weels属性とCarSpecnumber_of_doors属性を追加しました

EDITED-YET AGAIN : 私の見解では、仕様をいじるたびに型検証を行うことを避け、関連するクラスの 1 つに任せたいと考えていました。再開すると、新しい仕様オブジェクトを追加できるようになり、ビューの変更について心配する必要がなくなります.仕様に関連するオブジェクトのみ..

# CarSpec
if game_type == "A":
    stuff = CarSpec.restore_state(request, game_session)
# MotoSpec
elif game_type == "C":
    stuff = MotoSpec.restore_state(request, game_session)

EDITED : Spec クラスに restore_state を追加しましたが、循環インポートに関連するいくつかの問題を見つけたと思います..OMG..これは私を殺しています。私は.NETのバックグラウンドを持っています.Pythonは、この種のものでは簡単ではありません:S

4

4 に答える 4

1

シャーシ、ブランド、およびモデルの属性を Spec クラスに追加し、次にCarSpec および MotoSpec クラスのプロキシ モデルを使用し、car_brand()、motor_brand() などのメソッドを追加します。

于 2013-02-07T16:59:29.080 に答える
0

クラスの を削除することはできますが (class Metaオブジェクトが存在するように)。クラスのメソッドをオーバーライドしてインスタンス化またはオブジェクト化できるとは思いません。それはあなたに循環依存を与えるでしょう。オブジェクトの定義は、オブジェクトの定義に依存しています (は の子孫であるため)。オブジェクトの定義をオブジェクトに依存させることはできません(の定義に表示された場合)。SpecSpec__init__CarSpecMotoSpecCarSpecSpecCarSpecSpecSpecCarSpecCarSpecSpec__init__

個人的には、lysergia25 が提案するプロキシ モデルを使用し、プロキシの追加フィールドを非表示/要求する必要があると思います。

アップデート

Specすべてのフィールドを( 1つのサブクラスにのみ表示されるフィールドで)追加すると仮定するとblank=True, null=True、次のようなことができます-

class MotoSpec(Spec):
    class Meta:
        proxy = True

    def __init__(self, *args, **kwargs):
        super(MotoSpec, self).__init__(*args, **kwargs)
        self.fields['number_of_doors'].editable = False
        self.feilds['powered_wheels'].blank = False

number_of_doorsこれにより、必要な間、すべてのフォーム (管理者を含む) からフィールドが非表示になりますpowered_wheels

于 2013-02-07T16:59:51.160 に答える
0

提案:

class Spec(models.Model):
    x = models.IntegerField(default=20)
    y = models.CharField(max_length=100, blank=True)
    z = models.CharField(max_length=50, blank=True)
    brand = models.CharField(max_length=100, blank=True)
    model = models.CharField(max_length=50, blank=True)


class CarSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'A'})
    number_of_doors = models.IntegerField(default=2)
CarSpec._meta.get_field('brand').verbose_name = 'Car Brand'
CarSpec._meta.get_field('model').verbose_name = 'Car Model'


class MotoSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'C'})
    powered_weels = models.IntegerField(default=1)
MotoSpec._meta.get_field('brand').verbose_name = 'Motor Brand'
MotoSpec._meta.get_field('model').verbose_name = 'Motor Model'


class Chassis(models.Model):
    GAME_TYPES = (
        ('A', 'Car'),
        ('B', 'Truck'),
        ('C', 'Motorcycle')
    )

    name = models.CharField(max_length=50, blank=False)
    type = models.CharField(max_length=2, choices = GAME_TYPES, default="A")

または、詳細な名前を forms.py に入れることができます

class CarSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'A'})
    number_of_doors = models.IntegerField(default=2)


class MotoSpec(Spec):
    chassis = models.ForeignKey(Chassis, unique=True, limit_choices_to={'type':'C'})
    powered_weels = models.IntegerField(default=1)
于 2013-02-10T13:22:29.823 に答える
-1

django documentationで説明されているように、マルチテーブル継承を使用する必要があります

于 2013-02-07T15:59:39.613 に答える