Reputation: 146
I have a Django app where users would upload Images and certain functions would take the image file path to process them and save the result in the same model.
all of this would happen in the file upload view the problem is My functions take the file path which isn't created/committed in the DB yet as I don't save before calling those functions.
I tried overriding the save method in the models.py
and it didn't work so how can I call the functions after the upload in a convenient way ??
here's the function:
# The view for analysing images
def upload_view(request,pk=None):
patient = get_object_or_404(Patient,pk=pk)
if request.method == 'POST':
form = forms.ImageForm(request.POST,request.FILES)
if form.is_valid():
image = form.save(commit=False)
image.patient = patient
image.enhanced = main(image.original.path)
image.segmented = segment(image.enhanced.path)
image.enhanced.name = image.enhanced.path.split('media')[1]
image.segmented.name = image.enhanced.path.split('media')[1]
messages.success(request,"Image added successfully!")
image.save()
return HttpResponseRedirect(reverse_lazy('patients:patient_detail', kwargs={'pk' : image.patient.pk}))
else:
form = forms.ImageForm()
return render(request, 'patients/upload.html', {'form': form})
else:
form = forms.ImageForm()
return render(request, 'patients/upload.html', {'form': form})
image.original
is the uploaded image
the problem is the file path isn't passed correctly and the functions return errors bec of that. (it worked when I made the processing in a different view where it was accessed after the upload)
Upvotes: 0
Views: 540
Reputation: 8506
Before you call save()
on your model, the path to your image doesn't exist, or is temporary. You can fix this by first creating the model from the form, no need for commit=False
, assuming main
and segment
are PIL based functions that return images, you can use the ImageField.save() method to set the name at the same time:
if form.is_valid():
image = form.save() # this creates the model, the upload paths are created here!
image.patient = patient
image.enhanced.save("enhanced_" + image.original.name, main(image.original.path)) # I made this up to avoid conflicts in your storage
image.segmented.save("segmented_" + image.original.name, segment(image.enhanced.path))
image.save() # this updates the model with the new images
messages.success(request,"Image added successfully!") # I moved this here, more accurate, in case save fails....
return HttpResponseRedirect(reverse_lazy('patients:patient_detail', kwargs={'pk' : image.patient.pk}))
As you can see, you need two hits to the database to save your images. This assumes that enhanced and segmented fields are not required in the model.
Also, because image transformation is an expensive task, I'd check how to get this out of the request cycle, by using something like Celery or Django-RQ, that way, your app can still service request while making the transformations on the background.
Upvotes: 1