DOCUMENT GEN

One click, print-ready.

Project managers needed a clean, professional profile sheet for each project — location, role, images, key details — ready to go straight into a client deck or printed handout, no reformatting in Word.

PythonDjangoWeasyPrintCSS
Export Preview — project_profile.pdf
BCE — PROJECT PROFILE SHEET
LOCATIONNew Cairo, Egypt
OUR ROLEGeneral Contractor
STATUSIn Progress
Single export1 project → 1 PDF
instant
Bulk export?ids=12,14,19 → 3 PDFs combined
1 click
The Breakdown

The Problem

WeasyPrint has limited support for modern CSS layout — flexbox barely works, which is a problem when the page needs to look designed, not dumped out as raw content. Project images also needed to bleed cleanly to the page edge, and the export needed to work for one project or fifty at once.

What I Built

New fields on the Project model (location, our_role, profile_image, location_image) to support the profile layout, and a CSS table-based layout standing in for flexbox to get WeasyPrint to render the page as designed. Images extend full-bleed using WeasyPrint-safe CSS. A bulk export view accepts a list of project IDs via ?ids= and returns every requested sheet in one go.

Process

How it works.

01

Trigger

A project manager clicks "Export" on one project, or selects several and clicks "Bulk Export" instead.

02

Assemble

Project fields — location, role, images — get pulled into a CSS table-based template built to survive WeasyPrint's limited layout engine.

03

Render

WeasyPrint converts the assembled HTML/CSS into a print-ready PDF, images extending full-bleed to the page edge.

04

Deliver

A single export returns one PDF; a bulk export via ?ids= returns every requested sheet combined into one file.

Outcome
2
EXPORT MODES
SINGLE + BULK
4
NEW MODEL FIELDS
ADDED FOR THIS
1
CLICK TO EXPORT
ANY PROJECT COUNT
Why it matters

A profile sheet a project manager can generate and hand over in one click, with nothing to reformat, is the difference between a tool that actually gets used and one that quietly gets ignored in favor of copy-pasting into Word.