The World’s Largest Online Community for Developers
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.
If each car has one manufacturer, then you should use a foreign key from
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
Wheel models in your case). For the manufacturer, you probably want to
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() ...