Django ModelForm doesn't update instance but fails with IntegrityError
I'm having some really weird issue with a ModelForm
. Instead of saving the instance, it attempts to create the instance with the same primary key.
class Upload(models.Model):
file = models.FileField(upload_to=get_foundry_upload_name, null=False, blank=False)
filename = models.CharField(max_length=256, null=True, blank=True)
foundry = models.ForeignKey(Foundry, on_delete=models.CASCADE)
family = models.CharField(max_length=256, null=True, blank=True)
family_select = models.ForeignKey(Family, null=True, blank=True, on_delete=models.CASCADE)
style = models.CharField(max_length=256, null=True, blank=True)
style_select = models.ForeignKey(Style, null=True, blank=True, on_delete=models.CASCADE)
processed = models.BooleanField(default=False)
created = models.DateTimeField("Created", auto_now_add=True)
class UploadProcessForm(ModelForm):
class Meta:
model = Upload
fields = (
"filename",
"family",
"family_select",
"style",
"style_select",
)
def upload_process_row(request, foundry, id):
i = get_object_or_404(Upload, id=id, foundry=foundry)
upload_form = UploadProcessForm(instance=i)
if request.method == "POST":
upload_form = UploadProcessForm(request.POST, instance=i)
if upload_form.is_valid():
upload_form.save()
return render(request, "foundry/upload_process.row.html", {
"f": upload_form
})
django.db.utils.IntegrityError: duplicate key value violates unique constraint "foundry_upload_pkey" DETAIL: Key (id)=(1) already exists.
I'm certain this is some super trivial mistake, but I just cannot spot where I'm going wrong; imo this looks exactly like the textbook example. The upload_form.save()
always attempts to create a database entry, and with the instance's primary key. I'd just want to update the existing instance (that's the whole point of a ModelForm
, no?).
I've wiped the database table and migrations and recreated them fresh, just to be sure.
Due to lack of context I couldn't provide the solid solution but there are few things you can try for dubugging the issue.
Try clearing the cache if there’s any caching or transaction issues, Django might not recognize the instance. Ensure that migrations are fully applied, and consider clearing the session and restarting the development server.
Add a debugging statement before the save()
call to confirm that upload_form.instance
is indeed the same object and not a new one:
print(upload_form.instance.id)
You can explicitly set primary key as temporary workaround
if upload_form.is_valid():
obj = upload_form.save(commit=False)
obj.id = i.id # explicitly set the id to the existing instance's id (not very good practice)
obj.save()
The model's save
method used an wrong/outdated signature. It should be:
def save(self, **kwargs):
self.filename = self.file.name
super().save(**kwargs)
The original triggered the the commit when it should not, thus resulting in duplicate primary keys.