7.5 KiB
Embedded Templates Feature
Overview
The embedded templates feature allows templates to be stored within project files (.ppz) so they travel with the document. When loading projects, embedded templates take priority over local filesystem templates, ensuring projects can be opened on any machine without missing custom templates.
Key Benefits
✓ Portability: Templates travel with project files
✓ Self-contained: No dependency on local template files
✓ Priority: Embedded templates override filesystem templates
✓ Automatic: Templates are auto-embedded when used
✓ Backward Compatible: Projects without embedded templates work as before
How It Works
Template Priority Order
When loading a template by name, the system checks in this order:
- Embedded templates in the current project (highest priority)
- User templates in
~/.pyphotoalbum/templates/ - Built-in templates in
pyPhotoAlbum/templates/
Automatic Embedding
Templates are automatically embedded in projects when:
- Applying a template to a page with
apply_template_to_page() - Creating a new page from a template with
create_page_from_template()
You can disable auto-embedding by passing auto_embed=False to these methods.
Template Naming
Templates are listed with prefixes indicating their source:
[Embedded] Template Name- Embedded in current project[Built-in] Template Name- Built-in templateTemplate Name- User template from filesystem
Usage Examples
Basic Usage
from pyPhotoAlbum.project import Project, Page
from pyPhotoAlbum.template_manager import TemplateManager, Template
# Create a project
project = Project(name="My Album")
# Create template manager with project
template_manager = TemplateManager(project=project)
# Create a page from a template (auto-embeds by default)
template = template_manager.load_template("Grid_2x2")
page = template_manager.create_page_from_template(template, page_number=1)
project.add_page(page)
# The template is now embedded in the project!
print(project.embedded_templates.keys())
# Output: dict_keys(['Grid_2x2'])
Manual Embedding
# Manually embed a template
template = Template(name="Custom Layout")
# ... configure template ...
template_manager.embed_template(template)
Saving Templates
# Save to filesystem (default)
template_manager.save_template(template)
# Or embed in project instead
template_manager.save_template(template, embed_in_project=True)
Listing Templates
# List all available templates
templates = template_manager.list_templates()
# Returns: ['[Embedded] Custom', '[Built-in] Grid_2x2', 'MyUserTemplate', ...]
Loading Templates
# Load embedded template (priority)
template = template_manager.load_template("Custom")
# Load with explicit prefix
template = template_manager.load_template("[Embedded] Custom")
template = template_manager.load_template("[Built-in] Grid_2x2")
Disabling Auto-Embed
# Don't auto-embed when applying template
template_manager.apply_template_to_page(
template,
page,
auto_embed=False
)
# Don't auto-embed when creating page
page = template_manager.create_page_from_template(
template,
page_number=1,
auto_embed=False
)
Project Serialization
Embedded templates are automatically serialized when saving projects:
# Save project to ZIP file
from pyPhotoAlbum.project_serializer import save_to_zip
save_to_zip(project, "myalbum.ppz")
# Embedded templates are included in the .ppz file
When loading:
from pyPhotoAlbum.project_serializer import load_from_zip
project, error = load_from_zip("myalbum.ppz")
# Embedded templates are automatically restored
# Create template manager to access them
template_manager = TemplateManager(project=project)
templates = template_manager.list_templates()
Data Structure
Embedded templates are stored in the project's embedded_templates dictionary:
project.embedded_templates = {
"Template Name": {
"name": "Template Name",
"description": "Template description",
"page_size_mm": [210, 297],
"elements": [
{
"type": "placeholder",
"position": [10, 10],
"size": [100, 100],
# ... more element data
},
# ... more elements
]
},
# ... more templates
}
API Reference
TemplateManager
Constructor
TemplateManager(project=None)
Create a template manager. Pass a Project instance to enable embedded template support.
Methods
embed_template(template: Template)
Manually embed a template in the project.
load_template(name: str) -> Template
Load a template by name. Checks embedded templates first, then filesystem.
list_templates() -> List[str]
List all available templates with source prefixes.
save_template(template: Template, embed_in_project: bool = False)
Save template to filesystem or embed in project.
delete_template(name: str)
Delete a template (works with embedded and user templates).
apply_template_to_page(template, page, mode="replace", scale_mode="proportional", margin_percent=2.5, auto_embed=True)
Apply template to a page. Auto-embeds by default.
create_page_from_template(template, page_number=1, target_size_mm=None, scale_mode="proportional", auto_embed=True) -> Page
Create a new page from template. Auto-embeds by default.
Project
Attributes
embedded_templates: Dict[str, Dict[str, Any]]
Dictionary storing embedded template definitions.
Migration Guide
Existing Projects
Existing projects without embedded templates will continue to work normally. Templates will be auto-embedded when:
- You apply a template to a page
- You create a new page from a template
- You manually embed a template
Sharing Projects
When sharing projects:
- Templates are automatically embedded when used
- Save the project to .ppz format
- Share the .ppz file
- Recipients can open the project and all templates are available
No manual steps required!
Best Practices
- Let auto-embed work: The default behavior of auto-embedding templates ensures portability
- Save projects after using templates: Embedded templates are saved with the project
- Use descriptive template names: This helps identify templates in the list
- Test on different machines: Verify templates work when opening projects elsewhere
Troubleshooting
Q: Why isn't my template showing as embedded?
A: Ensure you're creating the TemplateManager with the project:
template_manager = TemplateManager(project=project)
Q: Can I convert filesystem templates to embedded?
A: Yes, just load and embed them:
template = template_manager.load_template("MyTemplate")
template_manager.embed_template(template)
Q: What happens if I have templates with the same name?
A: Embedded templates take priority over filesystem templates with the same name.
Q: Can I remove embedded templates?
A: Yes, use:
template_manager.delete_template("[Embedded] Template Name")
Implementation Details
- Templates are stored as JSON in the project's
embedded_templatesdictionary - Serialization includes embedded templates in the project.json within .ppz files
- Template manager checks embedded templates first when loading
- Auto-embed only happens if the template isn't already embedded
- All template operations preserve element properties (position, size, rotation, etc.)