2017-04-12 2 views
1

Ich schreibe eine Django-App, für die ich eine PDF erzeugen muss, mit reportlab, und speichere sie unter FileField. Mein Problem ist, dass meine Medien in S3 gespeichert sind, und ich weiß nicht, wie ich dieses PDF direkt in S3 speichern kann.Django/reportlab: Generierte PDF-Datei direkt in FileField in AWS speichern s3

Ich erstelle die pdf lokal dann lesen und speichern in das FileField in s3, dann Löschen der lokalen Version, aber ich frage mich, ob es eine bessere Lösung, wo ich die Datei direkt in S3 speichern kann.

hier ist, wie ich den Vertrag generieren jetzt:

#temporary folder name to generate contract locally 
folder_name = (
    '/tmp/' 
    + '/contracts/' 
    + gig.identifier 
    ) 
mkdir_p(folder_name) 
address = (
    folder_name 
    + '/contract_' 
    + lang 
    + '.pdf' 
) 
doc = SimpleDocTemplate(
    address, 
    pagesize=A4, 
    rightMargin=72, 
    leftMargin=72, 
    topMargin=120, 
    bottomMargin=18 
) 
doc.build(Story, 
      canvasmaker=LogoCanvas) 
local_file = open(address) 
pdf_file = File(local_file) 
contract = Contract.objects.create(lang=lang, gig=gig) 
contract.contract_file.save('contract_'+lang+'.pdf', pdf_file) 
contract.save() 
#remove temporary folder 
shutil.rmtree(folder_name) 
return True 

und die Vertragsmodell wie folgt definiert ist:

class Contract(models.Model): 
    gig = models.ForeignKey(Gig, related_name='contracts') 
    lang = models.CharField(max_length=10, default='') 
    contract_file = models.FileField(
     upload_to=get_contract_path, 
     blank=True, 
     null=True, 
     default=None 
    ) 

Antwort

0

Sie BytesIO zum Erstellen eines In-Memory-Stream statt einer Datei verwenden können Strom.

Sie müssen jedoch noch reportlab diesen Stream statt einer Datei verwenden.

Unter Berufung auf die userguide, bei 2.2 Mehr über die Leinwand, hat Canvas Konstruktor einen filename Parameter, der sowohl ein String oder ein Dateideskriptor sein kann. Ich habe es mit einem SimpleDocTemplate getestet, so dass es sollte für Sie arbeitet:

import io 
stream = io.BytesIO() 
doc = SimpleDocTemplate(
    stream, 
    pagesize=A4, 
    rightMargin=72, 
    leftMargin=72, 
    topMargin=120, 
    bottomMargin=18 
) 
doc.build(Story, 
      canvasmaker=LogoCanvas) 
pdf_buffer = stream.getBuffer() 

Ich weiß S3 nicht, aber ich bin zuversichtlich, dass dies genug ist, um Ihr Problem zu lösen. Zum Beispiel, wenn Sie jetzt diese pdf in eine Datei schreiben möchten, würden Sie tun:

file = open("contract.pdf", "wb") 
file.write(pdf_buffer)