All,
I am missing something fundamental about the underlying model for Django's ForeingKeys vs ManyToManyFields.
Suppose I am building an application about cars. I might have the following classes:
class Car(models.Model):
carName = models.CharField()
class Manufacturer(models.Model):
manufacturerName = models.CharField()
class Wheel(models.Model):
radius = models.IntegerField()
So far so good. Now there are some relations between these classes. A car has a manufacturer and has (four) tire(s). Conceptually, there is a difference though. The manufacturer is related via "aggregation"; a manufacturer can be associated to multiple cars; deleting a Car instance should not cause that car's manufacturer to be deleted as well. The wheels are related via "composition"; every four wheels associated with a car are associated with that and only that car; delete the car and the wheels should be deleted as well.
So, intuitively, that means that I ought to do the following:
class Car(models.Model):
carName = models.CharField()
manufacturer = models.ManyToManyField("Manufacturer")
wheels = models.ForeignKey("Wheel")
Ultimately, I want to use inlineformset_factories so that users can fill in details about a car, its manufacturer and wheels all at the same time. Something like this:
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)
But most of the documentation that I find suggests that the ForiegnKey should go from Wheel to Car. This seems backwards to me, since the Wheel_formset would then present the user with all of the fields for a Car ("carName") and not a Wheel ("radius").
Just the act of typing this question is making me confused. Can anybody shed some light on how I can build a form that has all of a car fields, and then all of a manufacturer fields, and then all of a wheel fields.
Thanks
If each car has one manufacturer, then you should use a foreign key from Car
to Manufacturer
. This will allow multiple cars to have the same manufacturer, and manufacturers will not be deleted when cars are deleted. A many to many field suggests that one car can have multiple manufacturers.
Wheel
should have a foreign key to Car
. This will allow multiple wheels to have the same car, and the default Django behaviour when a car is deleted will be to delete the wheels.
So your models should look something like this:
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")
For your view, I would first try to write views for the forms and formsets individually, and make sure you understand the relationships between your models before you bring them all together in one view.
This Stack Overflow question explains how to use a form and inline formset together at the same time (equivalent to the Car
and Wheel
models in your case). For the manufacturer, you probably want to exclude
the manufacturer
field from your CarForm
, then set it in your view before you save.
...
manufacturer = ManufacturerForm.save()
car = CarForm.save(commit=False)
car.manufacturer = manufacturer
car.save()
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With