changed from flask to generate the pdf directly with reportLab

This commit is contained in:
lorenz 2024-02-13 22:30:57 +01:00
parent 6c3937ae6a
commit 7b18fb10f1
7 changed files with 94 additions and 116 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pdf

97
app.py
View File

@ -1,9 +1,23 @@
from flask import Flask, render_template from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from datetime import datetime from datetime import datetime
import os import os
import re import re
import textwrap
app = Flask(__name__) # Konstanten für die Abmessungen
CIRCLE_RADIUS = 3 * mm
CIRCLE_DISTANCE = 80 * mm
TOP_MARGIN_TO_CENTER = 12 * mm
IMAGE_TOP_MARGIN = 28 * mm
IMAGE_HEIGHT = 60 * mm
TEXT_MARGIN = 5 * mm
LEFT_MARGIN_TO_CENTER = (A4[0] / 4) - (CIRCLE_DISTANCE / 2) # Zentriert zwischen den Tagen
IMAGE_SHIFT_UP = 1 * mm # Bild nach oben verschieben
DATE_SHIFT_DOWN = 8 * mm # Datum nach unten verschieben
TEXT_SHIFT_DOWN = 8 * mm # Text nach unten verschieben
def get_dates_from_images(image_directory): def get_dates_from_images(image_directory):
# Regular expression to match files with a date format YYYY-MM-DD # Regular expression to match files with a date format YYYY-MM-DD
@ -50,18 +64,81 @@ def get_image_and_text_for_date(date, image_directory, text_directory):
return image_file, text_content return image_file, text_content
def draw_circle(c, x, y):
c.circle(x, y, CIRCLE_RADIUS, stroke=1, fill=0)
@app.route('/') def create_pdf(pages_data, output_filename):
def calendar(): c = canvas.Canvas(output_filename, pagesize=A4)
c.setCreator('Lorenz B.')
c.setTitle('Calendar')
c.setAuthor('Lorenz B.')
c.setSubject('calendar generator')
width, height = A4
max_text_width = (width / 2) - (2 * TEXT_MARGIN)
DATE_FONT_SIZE = 20
DATE_FONT = "Helvetica-Bold"
for page in pages_data:
for index, day in enumerate(page):
c.setDash(1, 0)
c.setStrokeColor(colors.black)
# Berechnung der Positionen für jeden Tag
x = (index % 2) * (width / 2)
y = height - (index // 2 + 1) * (height / 2)
# Höhere Position für das Bild
image_y_position = y + (height / 2 - IMAGE_TOP_MARGIN - IMAGE_HEIGHT) + IMAGE_SHIFT_UP
# Kreise zeichnen
draw_circle(c, x + LEFT_MARGIN_TO_CENTER, y + height / 2 - TOP_MARGIN_TO_CENTER)
draw_circle(c, x + width / 2 - LEFT_MARGIN_TO_CENTER, y + height / 2 - TOP_MARGIN_TO_CENTER)
# Bild einfügen
if day['image_file']:
c.drawImage(day['image_file'], x, image_y_position, width=width / 2, height=IMAGE_HEIGHT, preserveAspectRatio=True, anchor='n')
# Datum direkt unter dem Bild einfügen
date_x_position = x + (width / 4) # Zentrum des Tagesbereichs
date_y_position = image_y_position - DATE_SHIFT_DOWN
date_str = day['date'].strftime('%A, %d.%m.%Y')
c.setFont(DATE_FONT, DATE_FONT_SIZE) # Schriftart und Schriftgröße setzen
date_width = c.stringWidth(date_str, DATE_FONT, DATE_FONT_SIZE)
c.drawString(date_x_position - (date_width / 2), date_y_position, date_str)
# Text unter dem Datum einfügen
text_y_position = date_y_position - TEXT_SHIFT_DOWN - 5 * mm # Extra Abstand nach einem größeren Datum
if day['text_content']:
c.setFont("Helvetica", 12) # Schriftart zurücksetzen für den Text
wrapped_text = textwrap.fill(day['text_content'], width=50) # Anpassen für die passende Zeilenlänge
text = c.beginText(x + TEXT_MARGIN, text_y_position)
for line in wrapped_text.split('\n'):
text.textLine(line)
c.drawText(text)
# Gestrichelte Linien zeichnen, falls notwendig
c.setDash(1, 2)
c.setStrokeColor(colors.grey)
if index % 2 == 0: # Vertikale Linie rechts für den Tag
c.line(x + width / 2, y, x + width / 2, y + height / 2)
if index < 2: # Horizontale Linie unten für den Tag
c.line(x, y, x + width / 2, y)
c.showPage()
c.save()
def main():
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(os.path.abspath(__file__))
image_directory = os.path.join(BASE_DIR, 'static', 'images') image_directory = os.path.join(BASE_DIR, 'images')
text_directory = os.path.join(BASE_DIR, 'texts') text_directory = os.path.join(BASE_DIR, 'texts')
# Get sorted dates from image files # Get sorted dates from image files
dates = get_dates_from_images(image_directory) dates = get_dates_from_images(image_directory)
if not dates: if not dates:
return "No images found with the correct date format in the name.", 404 print("No images found with the correct date format in the name.")
return
# Generate data for each date # Generate data for each date
pages_data = [] pages_data = []
@ -83,7 +160,11 @@ def calendar():
if days_data: if days_data:
pages_data.append(days_data) pages_data.append(days_data)
return render_template('index.html', pages=pages_data) # Create the PDF
output_filename = os.path.join(BASE_DIR, 'calendar.pdf')
create_pdf(pages_data, output_filename)
print("PDF created successfully.")
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True) main()

3
images/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.png
*.jpeg
*.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

View File

@ -1,107 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<style>
@media print,
screen {
body {
width: 210mm;
height: 297mm;
margin: 0mm 0mm 0mm 0mm;
padding: 0;
}
.page {
width: 210mm;
height: 297mm;
display: flex;
flex-wrap: wrap;
page-break-after: always;
}
.day {
width: 50%;
height: 50%;
box-sizing: border-box;
position: relative;
}
.circle {
width: 10mm;
height: 10mm;
position: absolute;
border-radius: 50%;
border: 1px solid black;
background-color: transparent;
}
.circle.top-left {
top: 10mm;
left: 10mm;
}
.circle.top-right {
top: 10mm;
right: 10mm;
}
.image-container {
margin-top: 28mm;
text-align: center;
height: 60mm;
}
.image-container img {
max-width: 100%;
max-height: 60mm;
height: auto;
width: auto;
object-fit: contain;
}
.date-info {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
}
.text {
padding-left: 5mm;
padding-right: 5mm;
font-family: 'Courier New', Courier, monospace;
color: #666666;
}
}
</style>
</head>
<body>
{% for page in pages %}
<div class="page">
{% for day in page %}
<div class="day" style="{{ 'border-right: 1px dashed grey; border-bottom: 1px dashed grey;' if loop.index0 == 0 else '' }}
{{ 'border-bottom: 1px dashed grey;' if loop.index0 == 1 else '' }}
{{ 'border-right: 1px dashed grey;' if loop.index0 == 2 else '' }}">
<div class="circle top-left"></div>
<div class="circle top-right"></div>
<div class="image-container">
{% if day.image_file %}
<img src="{{ url_for('static', filename=day.image_file) }}" alt="Bild für {{ day.date.strftime('%d. %B %Y') }}" />
{% endif %}
</div>
<div class="date-info">
<h1>{{ day.date.strftime('%A %d.%m.%Y') }}</h1>
</div>
<div class="text">
{% if day.text_content %}
<p>{{ day.text_content }}</p>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</body>
</html>

1
texts/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.txt

View File

@ -1 +0,0 @@
Beispiel Text