9

全部,

我缺少有关 Django 的 ForeingKeys 与 ManyToManyFields 基础模型的一些基本信息。

假设我正在构建一个关于汽车的应用程序。我可能有以下课程:

 class Car(models.Model):
   carName = models.CharField()

 class Manufacturer(models.Model):
   manufacturerName = models.CharField()

 class Wheel(models.Model):
   radius = models.IntegerField()

到现在为止还挺好。现在这些类之间有一些关系。一辆汽车有一个制造商并有(四个)轮胎。但从概念上讲,还是有区别的。制造商通过“聚合”关联;一个制造商可以与多辆汽车相关联;删除 Car 实例不应导致该汽车的制造商也被删除。轮子通过“组合”关联;与汽车相关的每四个车轮与该汽车相关联,并且仅与该汽车相关联;删除汽车,车轮也应删除。

所以,直觉上,这意味着我应该做以下事情:

 class Car(models.Model):
   carName = models.CharField()
   manufacturer = models.ManyToManyField("Manufacturer")
   wheels = models.ForeignKey("Wheel")

最终,我想使用 inlineformset_factories 以便用户可以同时填写有关汽车、制造商和车轮的详细信息。像这样的东西:

 class CarForm(ModelForm):
   class Meta:
     model = Car

 class ManufacturerForm(ModelForm):
   class Meta:
     model = Manufacturer

 class WheelForm(ModelForm):
   class Meta:
     model = Wheel

 Manufacturer_formset = inlineformset_factory(Car,Manufacturer,formset=ManufacturerForm)
 Wheel_formset = inlineformset_factory(Car,Wheel,formset=WheelForm)

但我发现的大多数文档都表明 ForiegnKey 应该从 Wheel 转到 Car。这对我来说似乎是倒退的,因为 Wheel_formset 然后会向用户显示 Car(“carName”)而不是 Wheel(“radius”)的所有字段。

只是输入这个问题的行为让我感到困惑。任何人都可以阐明我如何构建一个包含所有汽车字段的表单,然后是所有制造商字段,然后是所有车轮字段。

谢谢

4

1 回答 1

15

如果每辆车都有一个制造商,那么您应该使用外键 from Carto Manufacturer。这将允许多辆汽车拥有相同的制造商,并且在删除汽车时不会删除制造商。多对多字段表明一辆车可以有多个制造商。

Wheel应该有一个外键Car。这将允许多个车轮拥有同一辆车,并且当汽车被删除时,Django 的默认行为将是删除车轮。

所以你的模型应该是这样的:

class Manufacturer(models.Model):
    name = models.CharField()

class Car(models.Model):
    name = models.CharField()
    manufacturer = models.ForeignKey("Manufacturer")

class Wheel(models.Model):
    radius = models.IntegerField()
    car = models.ForeignKey("Car")

对于您的观点,我将首先尝试分别为表单和表单集编写视图,并确保您了解模型之间的关系,然后再将它们全部放在一个视图中。

这个Stack Overflow 问题解释了如何同时使用表单和内联表单集(相当于你的情况下的CarandWheel模型)。对于制造商,您可能希望从您excludemanufacturer字段中获取CarForm,然后在保存之前将其设置在您的视图中。

...
manufacturer = ManufacturerForm.save()
car = CarForm.save(commit=False)
car.manufacturer = manufacturer
car.save()
...
于 2012-01-15T21:20:03.330 回答