Rawkcy
Rawkcy

Reputation: 33

Django admin "Preview PDF" button

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

Answers (1)

Tisho
Tisho

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

Related Questions