IntegrityError when updating 2 models (related OneToOne) with Django CBV with 2 forms
I trying to update the linked OneToOne model in a CBV but got the error bellow.
I can not figure out why it doesn't update instead of create as I pass form2 with Patient instance
django.db.utils.IntegrityError: ERREUR: the value of a duplicate key breaks the unique constraint « Patient_inclusion_id_key » DETAIL: key « (inclusion_id)=(f4a60661-2b26-4ccb-b812-e9b26063df82) » already exist
class InclusionUpdate(SuccessMessageMixin, UpdateView):
model = Inclusion
form_class = InclusionForm
second_form_class = PatientForm
template_name = "web/inclusion_form.html"
success_message = "Inclusion mise à jour avec succès."
success_url = reverse_lazy('web:inclusion_list')
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.object = None
def get_context_data(self, **kwargs):
....
def form_valid(self, form, form2):
inclusion = form.save(commit=False)
inclusion.save()
patient = form2.save(commit=False) # I could comment his line or not dosesn't change
patient.save() #<= this line is raise integrityError
return super().form_valid(form)
def form_invalid(self, form, form2):
context = self.get_context_data(form=form, form2=form2)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
form2 = self.second_form_class(request.POST, instance=Patient.objects.get(inclusion=self.object)) if Patient.objects.filter(inclusion=self.object).exists() else self.second_form_class(request.POST)
if all((form.is_valid(), form2.is_valid())):
return self.form_valid(form, form2) #<= this line is executed
else:
return self.form_invalid(form, form2)
EDIT 2023-10-04
According to Django 4.1 documentation (link), this issue should be fixed using update_or_create but I still have the same IntegrityError
my form_valid méthod updated:
def form_valid(self, form, form2):
inclusion = form.save(commit=False)
inclusion.save()
# Récupérez les données du formulaire form2
patient_data = form2.cleaned_data
# Save Patient model updates
patient, created = Patient.objects.update_or_create(
uuid=patient_data['uuid'], # uuid as PK
defaults={**patient_data, 'inclusion': inclusion} inclusion as FK
)
return super().form_valid(form)