Reputation: 33
Desperately need help on this task; been hacking at it for a day now. The functionality is to translate text written by the admin through the admin interface to a PDF the user can view through the web application.
That functionality has been implemented except I want to be able to see the PDF I will generate before actually publishing it. So in the admin interface, I'm looking to create a "Preview PDF" button. Essentially it would save the current form (with new changes) generate the PDF so the changes can be seen, and rollback to the original state so no change can be seen by the outside world.
I'm tackling the problem by overriding the save function in models.
@transaction.commit_manually
def save(self, force_insert=False, force_update=False, using=None):
super(Doc, self).save(force_insert=force_insert, force_update=force_update, using=using)
if self.preview:
from lava_server.settings import common
# make a copy
doc_copy = self
doc_copy.id = None
# Prevent loopback
doc_copy.preview = False
transaction.rollback()
doc_copy.save()
common.TEMP_PDF_ID = doc_copy.id
else:
transaction.savepoint_commit(sid)
I've also overridden the response_change and response_add to redirect to the view that renders the PDF. The view deletes the doc_copy after the render.
To be honest, it was working I think but now it's giving me a
TransactionManagementError: Transaction managed block ended with pending COMMIT/ROLLBACK
It's probably because of my nested transaction in the save method? But I feel like I should seek for higher help on this in case I'm missing something fundamental or there's just a plain superior way of doing it.
Any help is much appreciated, thanks!
Upvotes: 2
Views: 1665
Reputation: 8482
This seems like a very complex way of doing it - this way you make it possible to create a savepoint and never commit/rollback it into DB, which may lead to database locks(like in your example).
I'd do it simpler - when hitting the "Preview PDF" button, just create the pdf and return it using
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=preview.pdf'
#print PDF to response
return response
This will download the PDF in your browser, and no saving will occur into the DB. You can preview it, and when everything seem OK - then save it in the regular way. Just save all other changes in the DB, so when reloading the page to keep them in the form.
Another solution could be to implement file status field for the PDF file, with status = "DRAFT|PUBLISHED", and to show to users only PUBLISHED versions, while DRAFT to be available in Admin only ...
Upvotes: 3