I have a Django app in my project I am currently working on called pharmcare, and I kind of getting into a unique constraint issue whenever I want to override the save()
method to insert/save the total
payment made by the patient so that the pharmacist that is creating the form or updating the patient’s record won’t perform the math manually. Whenever I used the form from CreateView
on the view.py without overriding the save method with the function I created dynamically to solve the math, it performed the work perfectly well, but in the admin panel, the answer wouldn’t appear there. However, if I tried using the save()
in my models.py
of the app I’d get that error. If I remove the save() method in the model, the error will disappear, and that’s not what I want, since I want it to be save in the db immediately the pharmacists finished creating or modifying the form. I had used the get_or_create
method to solve it but it remains abortive, and another option which I don’t want to use (since I want the site owner to have the option of deleting the pharmacist/organizer creating the record at ease same with the records s/he created) is the SET_NULL
for the on_delete
function of the foreign key. The database I am using is PostgreSQL btw.
Here is my pharmcare model of the patient table:
class Patient(models.Model):
medical_charge = models.PositiveBigIntegerField(blank=True, null=True,
verbose_name="amount paid (medical charge if any)")
notes = models.TextField(null=True, blank=True)
pharmacist = models.ForeignKey(
"Pharmacist", on_delete=models.SET_NULL, null=True, blank=True)
organization = models.ForeignKey(
'leads.UserProfile', on_delete=models.CASCADE)
user = models.ForeignKey(
'songs.User', on_delete=models.CASCADE)
patient = models.ForeignKey(
'PatientDetail', on_delete=models.CASCADE,
verbose_name='Patient-detail')
medical_history = models.ForeignKey(
'MedicationHistory',
on_delete=models.CASCADE)
total = models.PositiveBigIntegerField(editable=True, blank=True,
null=True, verbose_name="Total (auto-add)")
slug = models.SlugField(null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['id', '-date_created']
def __str__(self):
return self.patient.first_name
def get_total_charge(self) -> int:
total = 0
# check whether there is additional charges like drug price to be added
# if yes, then add medical charges to the total
if self.medical_charge:
amount_charged = self.patient.consultation + self.medical_charge
total += amount_charged
return total
total += self.patient.consultation
return total
# where the error is coming from
def save(self, *args, **kwargs):
""" override the save method to dynamically save the
total and slug in the db whenever form_valid() of the patient is
checked. """
self.total = self.get_total_charge()
self.slug = slug_modifier()
return super().save(self, *args, **kwargs)
My View:
class PatientCreateView(OrganizerPharmacistLoginRequiredMixin, CreateView):
""" Handles request-response cycle made by the admin/pharmacists to create
a patient"""
template_name = 'pharmcare/patients/patient-info-create.html'
form_class = PatientModelForm
# queryset = Patient.objects.all()
def get_queryset(self):
organization = self.request.user.userprofile
user = self.request.user
if user.is_organizer or user.is_pharmacist:
queryset = Patient.objects.filter(
organization=organization)
else:
queryset = Patient.objects.filter(
pharmacist=user.pharmacist.organization
)
queryset = queryset.filter(pharmacist__user=user)
return queryset
def form_valid(self, form: BaseModelForm) -> HttpResponse:
user = self.request.user
form = form.save(commit=False)
form.user = user
form.organization = user.userprofile
form.save()
# Patient.objects.get_or_create(pharmacist=user.pharmacist.organization)
return super(PatientCreateView, self).form_valid(form)
def get_success_url(self) -> str:
return reverse('pharmcare:patient-info')
The error message from my dev environment:
IntegrityError at /pharmcare/patient-info-create/
UNIQUE constraint failed: pharmcare_patient.id
Request Method: POST
Request URL: http://127.0.0.1:8000/pharmcare/patient-info-create/
Django Version: 4.2
Exception Type: IntegrityError
Exception Value:
UNIQUE constraint failed: pharmcare_patient.id
Exception Location: C:UsersUSERDesktopdj-testsenvLibsite-packagesdjangodbbackendssqlite3base.py, line 328, in execute
Raised during: pharmcare.views.patients.PatientCreateView
Python Executable: C:UsersUSERDesktopdj-testsenvScriptspython.exe
Python Version: 3.12.0
Python Path:
['C:\Users\USER\Desktop\dj-tests',
'C:\Users\USER\AppData\Local\Programs\Python\Python312\python312.zip',
'C:\Users\USER\AppData\Local\Programs\Python\Python312\DLLs',
'C:\Users\USER\AppData\Local\Programs\Python\Python312\Lib',
'C:\Users\USER\AppData\Local\Programs\Python\Python312',
'C:\Users\USER\Desktop\dj-tests\env',
'C:\Users\USER\Desktop\dj-tests\env\Lib\site-packages',
'C:\Users\USER\Desktop\dj-tests\env\Lib\site-packages\win32',
'C:\Users\USER\Desktop\dj-tests\env\Lib\site-packages\win32\lib',
'C:\Users\USER\Desktop\dj-tests\env\Lib\site-packages\Pythonwin']
Server time: Sat, 30 Dec 2023 18:02:51 +0000
I had also tried using self.object
provided by Django CBV
as well and I had tried looking at previous issues relating to my problem here in stackoverflow but none was able to sort my problem out, which 80% of them were using SET_NULL on their foreign key which I don’t want.
Please I need your answer on making this work because it kinda stuck my progress on my work for a day now. Thank you!
2
Answers
I used the answer provided above, and it didn't work however it really gave me a clue on what to do, so I had to dig more in the django documentation (when to use
save, update,delete methods
. The error I got wasAttributeError:'super' object has no attribute 'update'
.This works instead:
Thanks a bunch @Pycm
Use the below code. Use update, not save.