jinja_partials 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,84 @@
1
+ """
2
+ jinja_partials - Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks.
3
+ """
4
+
5
+ __version__ = '0.2.0'
6
+ __author__ = 'Michael Kennedy <michael@talkpython.fm>'
7
+ __all__ = [
8
+ 'register_extensions',
9
+ 'register_starlette_extensions',
10
+ 'register_environment',
11
+ 'render_partial',
12
+ 'generate_render_partial',
13
+ 'PartialsException',
14
+ ]
15
+
16
+ from functools import partial
17
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Union
18
+
19
+ from jinja2 import Environment
20
+ from markupsafe import Markup as Markup
21
+
22
+ try:
23
+ import flask
24
+ except ImportError:
25
+ flask = None
26
+
27
+ try:
28
+ import starlette
29
+ except ImportError:
30
+ starlette = None
31
+
32
+ if TYPE_CHECKING:
33
+ from flask import Flask
34
+ from starlette.templating import Jinja2Templates
35
+
36
+
37
+ class PartialsException(Exception):
38
+ pass
39
+
40
+
41
+ def render_partial(
42
+ template_name: str,
43
+ renderer: Optional[Callable[..., Any]] = None,
44
+ markup: bool = True,
45
+ **data: Any,
46
+ ) -> Union[Markup, str]:
47
+ if renderer is None:
48
+ if flask is None:
49
+ raise PartialsException('No renderer specified')
50
+ else:
51
+ renderer = flask.render_template
52
+
53
+ if markup:
54
+ return Markup(renderer(template_name, **data))
55
+
56
+ return renderer(template_name, **data)
57
+
58
+
59
+ def generate_render_partial(renderer: Callable[..., Any], markup: bool = True) -> Callable[..., Markup]:
60
+ return partial(render_partial, renderer=renderer, markup=markup)
61
+
62
+
63
+ def register_extensions(app: 'Flask'):
64
+ if flask is None:
65
+ raise PartialsException('Install Flask to use `register_extensions`')
66
+
67
+ app.jinja_env.globals.update(render_partial=generate_render_partial(flask.render_template))
68
+
69
+
70
+ def register_starlette_extensions(templates: 'Jinja2Templates'):
71
+ if starlette is None:
72
+ raise PartialsException('Install Starlette to use `register_starlette_extensions`')
73
+
74
+ def renderer(template_name: str, **data: Any) -> str:
75
+ return templates.get_template(template_name).render(**data)
76
+
77
+ templates.env.globals.update(render_partial=generate_render_partial(renderer))
78
+
79
+
80
+ def register_environment(env: Environment, markup: bool = False):
81
+ def renderer(template_name: str, **data: Any) -> str:
82
+ return env.get_template(template_name).render(**data)
83
+
84
+ env.globals.update(render_partial=generate_render_partial(renderer, markup=markup))
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Michael Kennedy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.1
2
+ Name: jinja_partials
3
+ Version: 0.2.0
4
+ Summary: Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks.
5
+ Home-page: https://github.com/mikeckennedy/jinja_partials
6
+ Author: Michael Kennedy
7
+ Author-email: michael@talkpython.fm
8
+ License: MIT
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.6
14
+ Classifier: Programming Language :: Python :: 3.7
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: jinja2
21
+
22
+ # Jinja Partials
23
+
24
+ Simple reuse of partial HTML page templates in the Jinja template language for Python web frameworks.
25
+ (There is also a [Pyramid/Chameleon version here](https://github.com/mikeckennedy/chameleon_partials).)
26
+
27
+ ## Overview
28
+
29
+ When building real-world web apps with Flask + Jinja2, it's easy to end up with repeated HTML fragments.
30
+ Just like organizing code for reuse, it would be ideal to reuse smaller sections of HTML template code.
31
+ That's what this library is all about.
32
+
33
+ ## Example
34
+
35
+ This project comes with a sample flask application (see the `example` folder). This app displays videos
36
+ that can be played on YouTube. The image, subtitle of author and view count are reused throughout the
37
+ app. Here's a visual:
38
+
39
+ ![](https://raw.githubusercontent.com/mikeckennedy/jinja_partials/main/readme_resources/reused-html-visual.png)
40
+
41
+ Check out the [**demo / example application**](https://github.com/mikeckennedy/jinja_partials/tree/main/example)
42
+ to see it in action.
43
+
44
+ ## Installation
45
+
46
+ It's just `pip install jinja-partials` and you're all set with this pure Python package.
47
+
48
+ ## Usage
49
+
50
+ Using the library is incredible easy. The first step is to register the partial method with Jinja and Flask.
51
+ Do this once at app startup:
52
+
53
+ ```python
54
+ import flask
55
+ import jinja_partials
56
+
57
+ app = flask.Flask(__name__)
58
+
59
+ jinja_partials.register_extensions(app)
60
+ # ...
61
+ ```
62
+
63
+ You can also use this library in your FastAPI (or Starlette) project!
64
+ ```python
65
+ from fastapi.templating import Jinja2Templates
66
+ # or `from starlette.templating import Jinja2Templates`
67
+
68
+ import jinja_partials
69
+
70
+ templates = Jinja2Templates("tests/test_templates")
71
+
72
+ jinja_partials.register_starlette_extensions(templates)
73
+ # ...
74
+ ```
75
+
76
+ Or directly using a jijna environment!
77
+ ```python
78
+ import jinja_partials
79
+ from jinja2 import Environment, FileSystemLoader
80
+
81
+ environment = Environment(loader=FileSystemLoader("tests/test_templates"))
82
+ jinja_partials.register_environment(environment)
83
+ # ...
84
+ ```
85
+
86
+ Next, you define your main HTML (Jinja2) templates as usual. Then
87
+ define your partial templates. I recommend locating and naming them accordingly:
88
+
89
+ ```
90
+ ├── templates
91
+ │   ├── home
92
+ │   │   ├── index.html
93
+ │   │   └── listing.html
94
+ │   └── shared
95
+ │   ├── _layout.html
96
+ │   └── partials
97
+ │   ├── video_image.html
98
+ │   └── video_square.html
99
+ ```
100
+
101
+ Notice the `partials` subfolder in the `templates/shared` folder.
102
+
103
+ The templates are just HTML fragments. Here is a stand-alone one for the YouTube thumbnail from
104
+ the example app:
105
+
106
+ ```html
107
+ <img src="https://img.youtube.com/vi/{{ video.id }}/maxresdefault.jpg"
108
+ class="img img-responsive {{ ' '.join(classes) }}"
109
+ alt="{{ video.title }}"
110
+ title="{{ video.title }}">
111
+ ```
112
+
113
+ Notice that an object called `video` and list of classes are passed in as the model.
114
+
115
+ Templates can also be nested. Here is the whole single video fragment with the image as well as other info
116
+ linking out to YouTube:
117
+
118
+ ```html
119
+ <div>
120
+ <a href="https://www.youtube.com/watch?v={{ video.id }}" target="_blank">
121
+ {{ render_partial('shared/partials/video_image.html', video=video) }}
122
+ </a>
123
+ <a href="https://www.youtube.com/watch?v={{ video.id }}" target="_blank"
124
+ class="author">{{ video.author }}</a>
125
+ <div class="views">{{ "{:,}".format(video.views) }} views</div>
126
+ </div>
127
+ ```
128
+
129
+ Now you see the `render_partial()` method. It takes the subpath into the templates folder and
130
+ any model data passed in as keyword arguments.
131
+
132
+ We can finally generate the list of video blocks as follows:
133
+
134
+ ```html
135
+ {% for v in videos %}
136
+
137
+ <div class="col-md-3 video">
138
+ {{ render_partial('shared/partials/video_square.html', video=v) }}
139
+ </div>
140
+
141
+ {% endfor %}
142
+ ```
143
+
144
+ This time, we reframe each item in the list from the outer template (called `v`) as the `video` model
145
+ in the inner HTML section.
146
+
147
+
148
+ ## Why not just use `include` or `macro` from Jinja?
149
+
150
+ The short answer is they are nearly the same, but both fall short in different ways.
151
+ For a more detailed response, see the discussion on [**issue #1**](https://github.com/mikeckennedy/jinja_partials/issues/1)
@@ -0,0 +1,6 @@
1
+ jinja_partials/__init__.py,sha256=ol5s2emjaxa3aDBU3fBpkYU10Ah12nabdxixKfh--4E,2385
2
+ jinja_partials-0.2.0.dist-info/LICENSE,sha256=B_XBSvJtJYaSzXE0o9ptgql9kUId_iA0d1_XlrYfcaM,1072
3
+ jinja_partials-0.2.0.dist-info/METADATA,sha256=EUv5PoKaCxZhorM-cvkH5HgSTp5TazTfK205_6WbJCE,4973
4
+ jinja_partials-0.2.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
5
+ jinja_partials-0.2.0.dist-info/top_level.txt,sha256=8ZW7w6eR_CzS9ZjcYGhRpjTn4Py9WwLeje0KuM5N7Ew,15
6
+ jinja_partials-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.42.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ jinja_partials