Presenter pattern to help manage the complexity of bloated controllers/views and logic-laden templates
Project description
Python Presenter
Overview
The Python Presenter is a library designed to address common architectural challenges in web application development by introducing a flexible, testable layer between application logic and presentation. Inspired by architectural patterns that separate concerns, this library provides a robust solution for managing view-specific logic and data preparation.
The Problem
As web applications grow in complexity, developers often encounter several architectural challenges:
- Logic Complexity: Application logic becomes increasingly complex, handling multiple responsibilities.
- Presentation Logic Creep: Template files begin to contain formatting, computation, and business logic.
- Testing Difficulties: Complex logic becomes challenging to test in isolation.
The Presenter Solution
The Python Presenter library introduces a dedicated layer that:
- Encapsulates presentation-specific data preparation
- Separates concerns between data retrieval and presentation
- Provides a clean, testable interface for presentation logic
- Simplifies application logic responsibilities
Key Benefits
- Improved Testability: Logic can be unit tested without setting up complex application environments
- Separation of Concerns: Cleanly separates data aggregation from presentation
- Flexible Architecture: Easily extensible to handle complex presentation requirements
- Enhanced Maintainability: Reduces complexity in application logic and templates
Installation
pip install python-presenter
Basic Usage
Simple Example
In your module, define a presenter.py
file, and map the model datapoints you want extensively.
# presenter.py
from python_presenter import BasePresenter as base_presenter
class ProjectPresenter(base_presenter):
def price_detail(self):
return self.obj.price_detail
def project_name(self):
return self.obj.project_name
def property_address(self):
return self.obj.property_address
def property_unit_type(self):
result = self.obj.property_unit_type
return property_types[result].value if result in property_types.__members__ else result
@property
def labels(self):
return {
'price_detail': 'Price Detail',
'project_name': 'Project Name',
'property_address': 'Property 7 Address', # you can author labels to be different from database column labels on the fly.
'property_unit_type': 'Property Unit Type',
}
This defines the specific object you want to render on the HTML template. Any data from the database that is not explicitly defined here will not appear on the template when using {% present_object model_name_or_app_name %}
in the template file. This approach allows you to preprocess and customize the data before presenting it in the template, keeping the logic out of the template itself. Additionally, it provides an opportunity to test the object at the code level, ensuring better maintainability and separation of concerns.
Django Templating:
The presenter_tag
is provided as a template tag to render objects using a specified presenter class. To use it, include the tag in your template with {% load presenter_tag %}
. Then, use the predefined present_object
method to render the objects defined in the presenter file you created. See below:
<!-- templates/whatever_template_file.html -->
{% extends "base.html" %}
{% load static %}
{% load presenter_tag %}
{% block content %}
{% for project in projects %}
{% present_object project as presented_project %}
<li><strong>{{ presented_project.labels.price_detail }}:</strong> {{ presented_project.price_detail }}</li>
<li><strong>{{ presented_project.labels.project_name }}:</strong> {{ presented_project.project_name }}</li>
<li><strong>{{ presented_project.labels.expected_profit }}:</strong> {{ presented_project.expected_profit }}</li>
<li><strong>{{ presented_project.labels.property_address }}:</strong> {{ presented_project.property_address }}</li>
<li><strong>{{ presented_project.labels.property_unit_type }}:</strong> {{ presented_project.property_unit_type }}</li>
<br><br>
<!-- Other project details -->
{% endfor %}
{% endblock %}
Flask Templating:
To be added soon!
When to Use
Consider using the Presenter pattern when your application requires:
- Complex data aggregation from multiple models
- Significant presentation-specific transformations
- Consolidated validation across multiple models
- Improved separation of concerns
Advanced Features
- Error collection and merging
- Complex data transformations
- Presentation-specific computations and formatting
Contributing
We welcome contributions! Please see our contributing guidelines for more information.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Acknowledgments
Inspired by architectural patterns that emphasize separation of concerns.
Mentions
Many thanks to JetBrains for supplying me with a license to use their product in the development of this tool.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file python_presenter-0.1.0.tar.gz
.
File metadata
- Download URL: python_presenter-0.1.0.tar.gz
- Upload date:
- Size: 9.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
6e8ecc7eb17eb8c9c163186a87a5d6d728c32181f862908274812cb8c5139fc2
|
|
MD5 |
259634bad67f617e5b621f144436774b
|
|
BLAKE2b-256 |
e1a1a282a006e11975198a5a73cd21238eff8df46b9573e55e40ad2c7506e643
|
File details
Details for the file python_presenter-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: python_presenter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.0.1 CPython/3.11.5
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 |
458d733cf9f1e5caa137a500342cb8171d2fbe5bdaecb70e708c2fc2d171961c
|
|
MD5 |
f13865d378bdb6f52de10942498e705f
|
|
BLAKE2b-256 |
6579c64b7526ce636f2e6cae3d7eaba9fe4f06f396c520b811d0b9e1e45e6d2b
|