[英]python SubClasses from a Class that inherits from models.Model
I have some doubts here... 我在这里有一些疑问...
Imagine that I have 3 classes: 想象一下,我有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'))
I was working with this 3 classes, but in my apps I would have to check the chassis type all the time in order to apply some business rules to each situation... I thought this would not be the correct approach.. so I planned this: 我正在使用这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
and have two Subclasses: 并具有两个子类:
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'))
Ok, until here all ok, changed nothing in my apps that worked with previous classes and all objects were being persisted in the database quite nicely as expected.. 好的,直到一切正常,在与以前的类一起使用的我的应用程序中没有进行任何更改,并且所有对象都按预期很好地保存在数据库中。
But, my problem remains.. Because I continue to instantiate CarSpec and MotoSpec and not Spec... but... I want to use Spec all the time instead of the extending classes... being so, what can I do to be able to instantiate a Spec object passing a Chassis to his init method in order to get a CarSpec or a MotoSpec from that (or other) method.. 但是,我的问题仍然存在。.因为我继续实例化CarSpec和MotoSpec而不是Spec ...但是...我想一直使用Spec而不是扩展类...既然如此,我该怎么做?能够实例化将Chassis传递到其init方法的Spec对象,以便从该(或其他)方法获取CarSpec或MotoSpec。
EDITED-IMPORTANT : I've added powered_weels attribute for MotoSpec and number_of_doors for CarSpec because I have some specific fields for each of the two Specs EDITED-IMPORTANT :我为MotoSpec添加了power_weels属性,为CarSpec添加了number_of_doors ,因为我为两个Spec中的每一个都有一些特定的字段
EDITED-YET AGAIN : In my views I wanted to avoid doing a type verification every time I mess around with Specs and leave that to one of the classes involved. 再次编辑 :在我看来,我想避免每次我弄乱Specs并将其留给其中一个涉及的类时进行类型验证。 Resuming, I want to be able to add a new Spec Object and not have to worry about changing my views.. only the objects related to Specs.. 继续,我希望能够添加一个新的Spec对象,而不必担心更改我的视图。
# 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 : I've added a restore_state on my Spec class, but then I think I find some problems related to circular imports.. OMG.. this is killing me. 编辑 :我在我的Spec类上添加了restore_state,但是随后我认为我发现了一些与循环导入有关的问题。OMG ..这使我丧命。 I have a .NET background, and python is not getting easy on me in this kinds of stuff :S 我有.NET背景,而python在这些方面对我来说并不容易:
将底架,品牌和模型属性添加到Spec类,然后对CarSpec和MotoSpec类使用代理模型 ,也许添加诸如car_brand(),motor_brand()等方法。
Although you could remove the class Meta
on the Spec
class (so that you have Spec
objects). 尽管您可以删除Spec
类上的class Meta
类(以便拥有Spec
对象)。 I don't think you can override the __init__
method on the class to instantiate CarSpec
or MotoSpec
objects. 我认为您无法重写类上的__init__
方法以实例化CarSpec
或MotoSpec
对象。 That would give you a circular dependancy; 那会给你循环依赖; The definition of CarSpec
objects relies on the definition of Spec
objects (because CarSpec
is a descendant of Spec
). CarSpec
对象的定义依赖于Spec
对象的定义(因为CarSpec
是Spec
的后代)。 You can't make the definition of Spec
objects dependant on CarSpec
objects (which it would be if CarSpec
appeared in Spec
's __init__
definition). 您不能使Spec
对象的定义依赖于CarSpec
对象(如果CarSpec
出现在Spec
的__init__
定义中,则将是这样)。
Personally I think you should use proxy models as suggested by lysergia25, and hide/require the additional fields in the proxy. 我个人认为您应该使用lysergia25建议的代理模型,并隐藏/要求代理中的其他字段。
UPDATE 更新
Assuming you add all fields to Spec
(with blank=True, null=True
on the fields that only appear in one subclass), then you can do something like - 假设您将所有字段都添加到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
This should hide the field number_of_doors
from all forms (inc admin), whilst requiring powered_wheels
. 这应该从所有表格(inc admin)中隐藏number_of_doors
字段,同时需要powered_wheels
。
Propose: 提出:
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")
OR you can put verbose name in forms.py 或者,您可以在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)
您应该使用多表继承,如Django文档中所述
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.