Skip to content

Instantly share code, notes, and snippets.

@cnk
Created September 15, 2020 17:50
Show Gist options
  • Save cnk/47197db70d5dd467918cd22b83538368 to your computer and use it in GitHub Desktop.
Save cnk/47197db70d5dd467918cd22b83538368 to your computer and use it in GitHub Desktop.
#################################################################################################################
# Patch the wagtaildocs.views.documents.edit view so that we keep the same file name if the user uploads a replacement
# with the same filename. The default appends 7 random characters to make the filename unique, which changes the URL.
# 2020-07-10 rrollins: Works with Wagtail 2.9.
# 2020-09-03 cnk: should work with Wagtail 2.11a
# #################################################################################################################
@permission_checker.require('change')
def edit_without_changing_filename(request, document_id):
Document = get_document_model()
DocumentForm = get_document_form(Document)
doc = get_object_or_404(Document, id=document_id)
if not document_permission_policy.user_has_permission_for_instance(request.user, 'change', doc):
return permission_denied(request)
if request.method == 'POST':
original_file = doc.file
form = DocumentForm(request.POST, request.FILES, instance=doc, user=request.user)
if form.is_valid():
if 'file' in form.changed_data:
doc = form.save(commit=False)
doc.file_size = doc.file.size
# Set new document file hash
doc.file.seek(0)
doc._set_file_hash(doc.file.read())
doc.file.seek(0)
# BEGIN PATCH
# Instead of uploading the new file first, and letting it potentially be renamed by the system,
# rename the _original_ file manually.
moved_filename = f'{original_file.name}-{uuid4()}'
original_file.storage.move(original_file.name, moved_filename)
try:
# The file being uploaded will keep its filename, because the original file's name cannot match it.
doc.save()
except Exception as exp:
# If anything goes wrong with the upload, rename the original file back to its original name,
# then propagate the exception.
original_file.storage.move(moved_filename, original_file.name)
raise exp
else:
# Saved the new file succeeded, so we can safely delete the original.
original_file.storage.delete(moved_filename)
# END PATCH
else:
doc = form.save()
# Reindex the document to make sure all tags are indexed
search_index.insert_or_update_object(doc)
messages.success(request, _("Document '{0}' updated").format(doc.title), buttons=[
messages.button(reverse('wagtaildocs:edit', args=(doc.id,)), _('Edit'))
])
return redirect('wagtaildocs:index')
else:
messages.error(request, _("The document could not be saved due to errors."))
else:
form = DocumentForm(instance=doc, user=request.user)
try:
local_path = doc.file.path
except NotImplementedError:
# Document is hosted externally (eg, S3)
local_path = None
if local_path:
# Give error if document file doesn't exist
if not os.path.isfile(local_path):
messages.error(
request,
_("The file could not be found. Please change the source or delete the document"),
buttons=[messages.button(reverse('wagtaildocs:delete', args=(doc.id,)), _('Delete'))]
)
return TemplateResponse(request, "wagtaildocs/documents/edit.html", {
'document': doc,
'filesize': doc.get_file_size(),
'form': form,
'user_can_delete': document_permission_policy.user_has_permission_for_instance(
request.user, 'delete', doc
),
})
wagtail.documents.views.documents.edit = edit_without_changing_filename
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment