1

I have a model Document, and the admin can upload an image to a FileField. When a document/image is successfully uploaded, I also save a sha256 "fingerprint" of the image to test if an admin tries to upload a duplicate image. If a duplicate image is detected, I don't save the duplicate image and display an error message to the admin through the messages framework. However, I also get the message that the document was successfully uploaded. How can I prevent this from happening?

My code in an abbreviated form:

class Document(Model):
    document_id = models.AutoField(primary_key=True)
    computed_sha256 = models.CharField(editable=False, max_length=64, default="foobar")
    storage_file_name = models.FileField('File name', upload_to=settings.DOCUMENT_FOLDER_ORIGINALS, default=settings.DEFAULT_IMAGE_XXXLARGE_PATH,)

class DocumentAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        if form.is_valid():
            if not change:
                # Uploading one or more images
                files = request.FILES.getlist('storage_file_name')
                if files:
                    for f in files:
                        # Check if this file has been uploaded before by checking the fingerprint
                        _file = form.cleaned_data["storage_file_name"]
                        sha256 = image_processing_utils.compute_sha256(_file)
                        duplicate_files = Document.objects.filter(computed_sha256 = sha256)
                        if len(duplicate_files) > 0:
                            messages.add_message(request, messages.WARNING, 'Uploading a duplicate of "%s" and it will not be saved' % f.name)
                            break;
                        # more image processing stuff    
            else:
                # some more image processing stuff              
                obj.metadata = form.cleaned_data['metadata']
                super().save_model(request, obj, form, change)

The resulting admin page with the two messages when I try to upload a duplicate image: The two messages on the admin page when a duplicate image is uploaded

I am not sure where Django is adding the positive message that the image was uploaded correctly. How do I go about removing it and just displaying the message that the duplicate image was not uploaded?

Thanks!

Mark

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
user1045680
  • 815
  • 2
  • 9
  • 19

2 Answers2

0

The success message gets sent after the system determines that the form is valid, on this line: https://github.com/django/django/blob/master/django/contrib/admin/options.py#L1244

There isn't a great way to hook in there, but I think that's because the work you're doing should really occur on the form rather than in the save_model function. To see how to edit a form on admin, look here. On that form's clean method, you should be able to do everything you're doing in the save_model method above.

Another option would be to empty out your messages before posting your warning message. Thus, you would have:

# Remove unnecessary success message
list(messages.get_messages(request))
messages.add_message(request, messages.WARNING, 'Uploading a duplicate of "%s" and it will not be saved' % f.name)
Ross Mechanic
  • 424
  • 3
  • 11
  • I am using the save_model method because I am allowing for multiple uploads at one time. I first thought of doing the duplicate file check in the clean method as you suggest, but I wasn't sure if I invalidated the one file field, if the rest of the uploads would be aborted, nor do I see how one could modify the upload file list if the file field is invalidated in the clean method. I could try it, but multiple file uploads seem to be counter intuitive to the way the admin change page/clean method works. Do you think I am correct in doing the file check in the save_model method? – user1045680 Apr 17 '20 at 23:37
  • Also, the link to edit the admin form did not come through in your post. Could you add it in a comment? – user1045680 Apr 17 '20 at 23:39
  • I added `list(messages.get_messages(request))` right before I add my error message as you suggested, but the "successfully saved" message still appears. – user1045680 Apr 18 '20 at 16:27
0

You need to use messages.set_level() just before messages.add_message() as shown below, then you can remove the default successfull message:

if len(duplicate_files) > 0:
    messages.set_level(request, messages.WARNING) # Here
    messages.add_message(request, messages.WARNING, 'Uploading a duplicate of "%s" and it will not be saved' % f.name)
    break;
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129