A modern, web-based Python app for generating customizable math worksheet PDFs. Supports multiple problem types, per-type term ranges, and a user-friendly web UI. Built with FastAPI and ReportLab. Originally forked from https://github.com/januschung/math-worksheet-generator/
Demo site: https://math-worksheet-generator-xse1.onrender.com (takes up to 60 seconds to load from demo host)
- Generate printable math worksheets as PDFs
- Supports multiplication, addition, subtraction, division, missing factor, and fraction comparison
- Per-type term range customization (e.g., 2..12)
- Modern, interactive web UI (no CLI required)
- REST API for programmatic access
- Inline PDF preview and download
- Bookmarkable URLs to recall specific configurations
- Python 3.8+
reportlabandfastapi(seerequirements.txt)
- Install dependencies:
pip install -r requirements.txt
- Run the web app:
python main.py
- Open your browser to http://localhost:8000
- Select one or more problem types.
- Optionally adjust the term ranges (defaults are shown and can be reset).
- Ranges use the
min..maxformat (e.g.3..12). Term1 is the first number for the chosen type and term2 is the second (for division that means divisor and quotient). - Examples with default limits:
- Multiplication:
3 × 19 - Addition:
50 + 99 - Subtraction:
99 - 10 - Division:
45 ÷ 5 (quotient 9) - Missing Factor:
2 × __ = 40 - Fraction Compare:
3/8 ? 5/9
- Multiplication:
- Set the number of problems per type.
- Choose how many problems appear in each section (defaults to 25).
- Click Generate to preview and download the worksheet PDF.
- After generating, the URL updates so you can bookmark or share the settings.
Generate a worksheet PDF.
- Request JSON:
{ "problem_types": ["multiplication", "addition"], "n": 100, "chunk": 25, "term1": "2..12", // optional, single-type only "term2": "2..12", // optional, single-type only "defaults": { // optional per-type overrides "multiplication": {"term1": "3..12", "term2": "2..15"} } } - Response:
{ "url": "/pdf/worksheet_xxx.pdf" }
Serve a generated PDF for inline display or download.
Return the default term1/term2 ranges for each problem type as a JSON object:
{
"multiplication": {"term1": "3..12", "term2": "2..19"},
"addition": {"term1": "50..300", "term2": "10..99"},
...
}- The web UI fetches
/defaultsand prepopulates the term range fields. - You can edit the ranges before generating a worksheet.
- To change the built-in defaults, edit
PROBLEM_DEFAULTSinworksheet_core.py.
- All worksheet logic is in
worksheet_core.py. - To add a new problem type:
- Create a new class inheriting from
MathProblem. - Add it to
PROBLEM_DEFAULTSandPROBLEM_CLASS_MAPinmain.py. - Update the web UI HTML if you want it selectable.
- Create a new class inheriting from
import requests
payload = {
"problem_types": ["multiplication"],
"n": 50,
"chunk": 25,
"term1": "2..12",
"term2": "2..12"
}
r = requests.post("http://localhost:8000/generate", json=payload)
print(r.json()) # {"url": "/pdf/worksheet_xxx.pdf"}- There is no CLI interface; all usage is via the web UI or API.
- All worksheet generation is stateless and per-request.
For LAN or production use, deploy with Docker Compose for easy management, automatic restarts, and persistent storage.
-
Build and start the app:
docker compose up -d
This will build the image and start the service in the background.
-
Access the app:
- Open http://localhost:8000 or use your server's IP on your LAN.
-
Persist generated worksheets:
- The
generated/directory is mapped to a Docker volume and will persist across restarts and upgrades.
- The
-
Stop the app:
docker compose down
-
Restart the app:
docker compose up -d
-
Update the app:
- Pull the latest code, then rebuild:
git pull docker compose build docker compose up -d
- Pull the latest code, then rebuild:
-
Automatic restart:
- The service uses
restart: unless-stoppedand will automatically restart after a server reboot or crash.
- The service uses
For quick, one-off tests (not recommended for production):
docker run --rm -p 8000:8000 \
-v $(pwd):/app -w /app python:3.12-slim \
sh -c "pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0"- This does not persist generated files or restart automatically.
For more details, see the code and docstrings in main.py and worksheet_core.py.
