我在这里有些疑惑......
想象一下,我有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
并有两个子类:
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而不是扩展类...就这样,我能做什么?能够实例化一个Spec对象,将一个Chassis传递给他的 init 方法,以便从该(或其他)方法获得CarSpec或MotoSpec ..
已编辑 - 重要:我已为 MotSpec 添加了 Powered_weels 属性,为 CarSpec添加了 number_of_doors 因为我为两个规格中的每一个都有一些特定的字段
EDITED-YET AGAIN :在我的观点中,我希望每次使用Specs时都避免进行类型验证,并将其留给其中一个类。恢复,我希望能够添加一个新的Spec对象,而不必担心改变我的视图..只有与Specs相关的对象..
# CarSpec
if game_type == "A":
stuff = CarSpec.restore_state(request, game_session)
# MotoSpec
elif game_type == "C":
stuff = MotoSpec.restore_state(request, game_session)
已编辑:我在我的Spec类上添加了restore_state,但后来我觉得我发现了一些与循环导入有关的问题..天啊......这让我很伤心。我有一个.NET背景,而python对我来说并不容易:S
答案 0 :(得分:1)
将chasis,品牌和模型属性添加到Spec类,然后将proxy models用于CarSpec和MotoSpec类,也可以添加car_brand(),motor_brand()等方法......
答案 1 :(得分:0)
虽然您可以删除class Meta
类上的Spec
(以便拥有Spec
个对象)。我不认为您可以覆盖类上的__init__
方法来实例化CarSpec
或MotoSpec
个对象。这会给你一个循环的依赖; CarSpec
对象的定义依赖于Spec
个对象的定义(因为CarSpec
是Spec
的后代)。您无法定义Spec
个对象取决于CarSpec
个对象(如果CarSpec
Spec
出现__init__
Spec
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
定义)。
我个人认为你应该使用lysergia25建议的代理模型,并隐藏/要求代理中的其他字段。
更新
假设您将所有字段添加到{{1}}({{1}}只显示在一个子类中的字段上),那么您可以执行类似的操作 -
{{1}}
这应隐藏所有表单(包含管理员)中的字段{{1}},同时需要{{1}}。
答案 2 :(得分: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)
答案 3 :(得分:-1)
您应该使用多重继承,如django documentation
中所述