Hi folks, first-time Djangoer here. I’m building a site which has quite complex models, including some many-to-many fields. When saving a new entry into a model, Django throws ValueError: "<CameraModel: Canon Canonflex>" needs to have a value for field "id" before this many-to-many relationship can be used.
I understand this is because I need to save the first model before I can use the id of the new record in the second model, but I’m struggling with how to actually make it do this. I’ve looked at examples but I can’t really relate them to my models.
Am I correct that I need to override def save
in my form? If someone could give an example that would be great - thanks.
# models.py
class CameraModel(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE,
help_text='Manufacturer of this camera model')
model = models.CharField(help_text='The model name of the camera', max_length=45)
# ...about 20 others fields here...
shutter_speeds = models.ManyToManyField(ShutterSpeed, blank=True)
metering_modes = models.ManyToManyField(MeteringMode, blank=True)
exposure_programs = models.ManyToManyField(ExposureProgram, blank=True)
class MeteringMode(models.Model):
name = models.CharField(help_text='Name of metering mode as defined by EXIF tag MeteringMode', max_length=45)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "metering modes"
class ExposureProgram(models.Model):
name = models.CharField(help_text='Name of exposure program as defined by EXIF tag ExposureProgram', max_length=45)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "exposure programs"
# forms.py
class CameraModelForm(ModelForm):
class Meta:
model = CameraModel
fields = '__all__'
def __init__(self, *args, **kwargs):
super(CameraModelForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Fieldset(
'Basics',
'manufacturer',
'model',
'disambiguation',
'introduced',
'discontinued',
'format',
'negative_size',
),
Div(
TabHolder(
Tab('Interchangeable lens',
Fieldset(
'Lens mount',
'mount',
),
),
Tab('Fixed lens',
Fieldset(
'Lens',
'lens_manufacturer',
'lens_model_name',
),
Fieldset(
'Optics',
'zoom',
AppendedText('min_focal_length', 'mm'),
AppendedText('max_focal_length', 'mm'),
AppendedText('closest_focus', 'cm'),
PrependedText('max_aperture', 'f/'),
PrependedText('min_aperture', 'f/'),
'elements',
'groups',
AppendedText('nominal_min_angle_diag', '°'),
AppendedText('nominal_max_angle_diag', '°'),
'rectilinear',
AppendedText('image_circle', 'mm'),
'formula',
'aperture_blades',
'coating',
AppendedText('magnification', '×'),
),
Fieldset(
'Physical',
AppendedText('filter_thread', 'mm'),
'hood',
),
Fieldset(
'Misc',
'exif_lenstype',
),
),
),
css_class="border",
),
Fieldset(
'Physical',
'body_type',
AppendedText('weight', 'g'),
),
Fieldset(
'Focus',
'focus_type',
AppendedText('viewfinder_coverage', '%'),
'af_points',
),
Fieldset(
'Metering',
'metering',
'metering_type',
InlineCheckboxes('metering_modes'),
InlineCheckboxes('exposure_programs'),
'min_iso',
'max_iso',
'meter_min_ev',
'meter_max_ev',
),
Fieldset(
'Shutter',
'shutter_type',
'shutter_model',
InlineCheckboxes('shutter_speeds'),
'bulb',
'time',
),
Fieldset(
'Flash',
'int_flash',
'int_flash_gn',
'ext_flash',
'flash_metering',
'pc_sync',
'shoe',
'x_sync',
),
Fieldset(
'Battery',
'battery_qty',
'battery_type',
),
Fieldset(
'Features',
'cable_release',
'dof_preview',
'mirror_lockup',
'tripod',
'power_drive',
AppendedText('continuous_fps', 'fps'),
),
Fieldset(
'Misc',
'notes',
),
FormActions(
Submit('save', 'Save changes'),
Button('cancel', 'Cancel')
)
)