├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── example
├── app.py
├── requirements.txt
└── templates
│ └── index.html
├── flask_toastr.py
├── setup.py
└── tests
└── test_flask_toastr.py
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 | custom: ['https://www.paypal.com/donate/?cmd=_donations&business=5QJ62BNMRC75W¤cy_code=USD&source=url']
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 | .vscode
93 |
94 | # Spyder project settings
95 | .spyderproject
96 | .spyproject
97 |
98 | # Rope project settings
99 | .ropeproject
100 |
101 | # mkdocs documentation
102 | /site
103 |
104 | # mypy
105 | .mypy_cache/
106 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Wilton Rodrigues
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Flask-Toastr
2 | ============
3 |
4 | [](https://www.python.org/download/releases/3.4.0/) [](https://www.python.org/download/releases/2.7.2/) [](https://github.com/wiltonsr/Flask-Toastr/blob/master/README.md)
5 |
6 | Showing Flask's flash non-blocking notifications in templates using [toastr](https://github.com/CodeSeven/toastr).
7 |
8 | Donate to help keep this project maintained.
9 |
10 |
11 |
12 | Quick Start
13 | -----------
14 |
15 | Step 1: Initialize the extension:
16 |
17 | from flask_toastr import Toastr
18 | toastr = Toastr(app)
19 |
20 | Step 2: In your `
` and bottom of ``sections of your base template add the following code:
21 |
22 | ```html
23 |
24 |
25 | {{ toastr.include_jquery() }}
26 | {{ toastr.include_toastr_css() }}
27 | {{ toastr.message() }}
28 |
29 |
30 | {{ toastr.include_toastr_js() }}
31 |
32 |
33 | ```
34 |
35 | This extension also supports the [Flask application factory pattern](http://flask.pocoo.org/docs/latest/patterns/appfactories/) by allowing you to create a Toastr object and then separately initialize it for an app:
36 |
37 | ```python
38 | toastr = Toastr()
39 |
40 | def create_app(config):
41 | app = Flask(__name__)
42 | app.config.from_object(config)
43 | # initialize toastr on the app within create_app()
44 | toastr.init_app(app)
45 |
46 | app = create_app(prod_config)
47 | ```
48 |
49 | Note that jQuery is required. If you are already including it on your own then you can remove the `include_jquery()` line. Secure HTTP is used if the request under which these are executed is secure.
50 |
51 | The `include_jquery()`, `include_toastr_js()` and `include_toastr_css()` methods take some optional arguments. If you pass a `version` argument to any of these calls, then the requested version will be loaded from the default CDN. In addition, it is also possible to pass `js_filename` and `css_filename` to `include_toastr_js()` and `include_toastr_css()`, respectively.
52 |
53 | Step 3: Use the `flash()` method with or without category in your views. For example:
54 |
55 | ```python
56 | @app.route('/')
57 | def index():
58 | flash("All OK")
59 | flash("All OK", 'success')
60 | flash("All Normal", 'info')
61 | flash("Not So OK", 'error')
62 | flash("So So", 'warning')
63 | return render_template('index.html')
64 | ```
65 |
66 | Or you could also use `flash()` method with custom titles, see [#14](https://github.com/wiltonsr/Flask-Toastr/issues/14) for details:
67 |
68 | ```python
69 | @app.route('/')
70 | def index():
71 | flash("Message", 'Custom Title')
72 | flash({'title': "Custom Title", 'message': "Error Message"}, 'error')
73 | return render_template('index.html')
74 | ```
75 |
76 | Step 4: Enjoy
77 |
78 | Parameters
79 | --------
80 |
81 | Config | Default | Possible Values | Description | Reference |
82 | ------------------------- | ----------------- | ----------------------- | ------------- | --------------------|
83 | TOASTR_VERSION | '2.1.4' | [Releases from here](https://github.com/CodeSeven/toastr/releases) | Version of Toastr | https://github.com/CodeSeven/toastr/tags |
84 | TOASTR_JQUERY_VERSION | '2.1.0' | [Releases from here](https://github.com/jquery/jquery/releases) | Version of JQuery | https://releases.jquery.com/jquery/ |
85 | TOASTR_CSS_FILENAME | 'toastr.min.css' | CDN file name | CSS Filename used in CDN Toastr's link | https://github.com/CodeSeven/toastr#cdns |
86 | TOASTR_JS_FILENAME | 'toastr.min.js' | CDN file name | JS Filename used in CDN Toastr's link | https://github.com/CodeSeven/toastr#cdns |
87 | TOASTR_CLOSE_BUTTON | 'true' | 'true' or 'false' | Enable or Disable close button | https://github.com/CodeSeven/toastr#close-button |
88 | TOASTR_SHOW_EASING | 'swing' | 'swing' or 'linear' | Override the animation easing to show the toasts | https://github.com/CodeSeven/toastr#animation-options |
89 | TOASTR_HIDE_EASING | 'linear' | 'swing' or 'linear' | Override the animation easing to hide the toasts | https://github.com/CodeSeven/toastr#animation-options |
90 | TOASTR_CLOSE_EASING | 'linear' | 'swing' or 'linear' | Override the animation easing to close the toasts | https://github.com/CodeSeven/toastr#animation-options |
91 | TOASTR_SHOW_METHOD | 'fadeIn' | 'fadeIn', 'fadeOut', 'slideDown', 'slideUp, 'show', 'hide' | Override the animation method to show the toasts | https://github.com/CodeSeven/toastr#animation-options |
92 | TOASTR_HIDE_METHOD | 'fadeOut' | 'fadeIn', 'fadeOut', 'slideDown', 'slideUp, 'show', 'hide' | Override the animation method to hide the toasts | https://github.com/CodeSeven/toastr#animation-options |
93 | TOASTR_CLOSE_METHOD | 'fadeOut' | 'fadeIn', 'fadeOut', 'slideDown', 'slideUp, 'show', 'hide' | Override the animation method to close the toasts | https://github.com/CodeSeven/toastr#animation-options |
94 | TOASTR_TIMEOUT | 15000 | any `int` value (in ms) | Time to notification close | https://github.com/CodeSeven/toastr#timeouts |
95 | TOASTR_EXTENDED_TIMEOUT | 1000 | any `int` value (in ms) | Time to notification close after hover mouse or click | https://github.com/CodeSeven/toastr#timeouts |
96 | TOASTR_POSITION_CLASS | 'toast-top-right' | 'toast-top-right', 'toast-bottom-right', 'toast-bottom-left', 'toast-top-left', 'toast-top-full-width', 'toast-bottom-full-width', 'toast-top-center', 'toast-bottom-center' | Notification Positon | https://codeseven.github.io/toastr/demo.html |
97 | TOASTR_PREVENT_DUPLICATES | 'false' | 'true' or 'false' | Doesn't show same notification | https://github.com/CodeSeven/toastr#prevent-duplicates |
98 | TOASTR_NEWS_ON_TOP | 'false' | 'true' or 'false' | Notification's aparition order | https://github.com/CodeSeven/toastr#display-sequence |
99 | TOASTR_PROGRESS_BAR | 'true' | 'true' or 'false' | Enable or Disable progress bar | https://github.com/CodeSeven/toastr#progress-bar |
100 | TOASTR_OPACITY | True | True or False | Enable or Disable notification's opacity | https://stackoverflow.com/a/17640150/7041939 |
101 |
102 | Note: The values `true` and `false` are passed to JS, that is Case Sensitive.
103 | Therefore they must be passed in lowercase.
104 |
105 | Examples
106 | --------
107 |
108 | ```
109 | To run the example in your local environment:
110 |
111 | 1. Clone the repository:
112 |
113 | git clone https://github.com/wiltonsr/Flask-Toastr.git
114 | cd Flask-Toastr
115 |
116 | 2. Create and activate a virtual environment:
117 |
118 | virtualenv env
119 | source env/bin/activate
120 |
121 | 3. Install requirements:
122 |
123 | pip install -r 'example/requirements.txt'
124 |
125 | 4. Run the application:
126 |
127 | python example/app.py
128 | ```
129 |
130 | Function Reference
131 | ------------------
132 |
133 | Consult the [toastr documentation](https://github.com/CodeSeven/toastr#toastr) for more details.
134 |
135 | Development
136 | -----------
137 |
138 | This extension is just a project to improve my python and flask skills. Any suggestions or tips are welcome.
139 |
--------------------------------------------------------------------------------
/example/app.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, flash, render_template
2 | from flask_toastr import Toastr
3 |
4 | app = Flask(__name__)
5 | toastr = Toastr(app)
6 | app.config['SECRET_KEY'] = 'you-will-never-guess'
7 |
8 | @app.route('/')
9 | def index():
10 | # Default Title
11 | flash("Info Category and Default Title")
12 | flash("Info Category and Default Title", 'info')
13 | flash("Success Category and Default Title", 'success')
14 | flash("Error Category and Default Title", 'error')
15 | flash("Warning Category and Default Title", 'warning')
16 | # Custom Title
17 | flash("Info Category", 'Custom Title')
18 | flash({'title': "Custom Title", 'message': "Info Category"})
19 | flash({'title': "Custom Title", 'message': "Error Category"}, 'error')
20 | return render_template('index.html')
21 |
22 |
23 | if __name__ == '__main__':
24 | app.run(debug=True)
25 |
--------------------------------------------------------------------------------
/example/requirements.txt:
--------------------------------------------------------------------------------
1 | Flask
2 | Flask-Toastr
3 |
--------------------------------------------------------------------------------
/example/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Flask-Toastr Example App
4 | {{ toastr.include_jquery() }}
5 | {{ toastr.include_toastr_css() }}
6 | {{ toastr.message() }}
7 |
8 |
9 |
10 |
Flask-Toastr Example App - notification popup box using toastr JS Plugin
11 |
12 |
13 | {{ toastr.include_toastr_js() }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/flask_toastr.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | try:
3 | from jinja2 import Markup
4 | except ImportError:
5 | from markupsafe import Markup
6 | from jinja2 import Template
7 | from flask import current_app, render_template, get_flashed_messages
8 |
9 |
10 | class _toastr(object):
11 | @staticmethod
12 | def include_toastr_js(version=None, js_filename=None):
13 | if version is None:
14 | version = current_app.config.get('TOASTR_VERSION')
15 | if js_filename is None:
16 | js_filename = current_app.config.get('TOASTR_JS_FILENAME')
17 | js = '\n'.format(version, js_filename)
19 | return Markup(js)
20 |
21 | @staticmethod
22 | def include_toastr_css(version=None, css_filename=None):
23 | if version is None:
24 | version = current_app.config.get('TOASTR_VERSION')
25 | if css_filename is None:
26 | css_filename = current_app.config.get('TOASTR_CSS_FILENAME')
27 | css = '\n'.format(
29 | version,
30 | css_filename
31 | )
32 | if current_app.config.get('TOASTR_OPACITY'):
33 | return Markup(css)
34 | else:
35 | return Markup('''
36 | {0}'''.format(css))
41 |
42 | @staticmethod
43 | def include_jquery(version=None):
44 | if version is None:
45 | version = current_app.config.get('TOASTR_JQUERY_VERSION')
46 | js = (''.format(version))
48 | return Markup(js)
49 |
50 | @staticmethod
51 | def message():
52 | toastr_options = 'toastr.options.closeButton = %s; \
53 | toastr.options.showEasing = \"%s\"; \
54 | toastr.options.hideEasing = \"%s\"; \
55 | toastr.options.closeEasing = \"%s\"; \
56 | toastr.options.showMethod = \"%s\"; \
57 | toastr.options.hideMethod = \"%s\"; \
58 | toastr.options.closeMethod = \"%s\"; \
59 | toastr.options.timeOut = %s; \
60 | toastr.options.extendedTimeOut = %s; \
61 | toastr.options.positionClass = \"%s\"; \
62 | toastr.options.preventDuplicates = %s; \
63 | toastr.options.newestOnTop = %s; \
64 | toastr.options.progressBar = %s; ' % (
65 | current_app.config.get('TOASTR_CLOSE_BUTTON'),
66 | current_app.config.get('TOASTR_SHOW_EASING'),
67 | current_app.config.get('TOASTR_HIDE_EASING'),
68 | current_app.config.get('TOASTR_CLOSE_EASING'),
69 | current_app.config.get('TOASTR_SHOW_METHOD'),
70 | current_app.config.get('TOASTR_HIDE_METHOD'),
71 | current_app.config.get('TOASTR_CLOSE_METHOD'),
72 | current_app.config.get('TOASTR_TIMEOUT'),
73 | current_app.config.get('TOASTR_EXTENDED_TIMEOUT'),
74 | current_app.config.get('TOASTR_POSITION_CLASS'),
75 | current_app.config.get('TOASTR_PREVENT_DUPLICATES'),
76 | current_app.config.get('TOASTR_NEWS_ON_TOP'),
77 | current_app.config.get('TOASTR_PROGRESS_BAR'))
78 | message = Template('''
79 | {% with messages = get_flashed_messages(with_categories=true) %}
80 | {% if messages %}
81 |
100 | {% endif %}
101 | {% endwith %}
102 | ''')
103 | return Markup(render_template(
104 | message,
105 | get_flashed_messages=get_flashed_messages,
106 | toastr_options=toastr_options)
107 | )
108 |
109 |
110 | class Toastr(object):
111 | def __init__(self, app=None):
112 | if app is not None:
113 | self.init_app(app)
114 |
115 | def init_app(self, app):
116 | if not hasattr(app, 'extensions'):
117 | app.extensions = {}
118 | app.extensions['toastr'] = _toastr
119 | app.context_processor(self.context_processor)
120 |
121 | app.config.setdefault('TOASTR_VERSION', '2.1.4')
122 | app.config.setdefault('TOASTR_JQUERY_VERSION', '2.1.0')
123 | app.config.setdefault('TOASTR_CSS_FILENAME', 'toastr.min.css')
124 | app.config.setdefault('TOASTR_JS_FILENAME', 'toastr.min.js')
125 |
126 | app.config.setdefault('TOASTR_CLOSE_BUTTON', 'true')
127 | app.config.setdefault('TOASTR_SHOW_EASING', 'swing')
128 | app.config.setdefault('TOASTR_HIDE_EASING', 'linear')
129 | app.config.setdefault('TOASTR_CLOSE_EASING', 'linear')
130 | app.config.setdefault('TOASTR_SHOW_METHOD', 'fadeIn')
131 | app.config.setdefault('TOASTR_HIDE_METHOD', 'fadeOut')
132 | app.config.setdefault('TOASTR_CLOSE_METHOD', 'fadeOut')
133 | app.config.setdefault('TOASTR_TIMEOUT', 15000)
134 | app.config.setdefault('TOASTR_EXTENDED_TIMEOUT', 1000)
135 | app.config.setdefault('TOASTR_POSITION_CLASS', 'toast-top-right')
136 | app.config.setdefault('TOASTR_PREVENT_DUPLICATES', 'false')
137 | app.config.setdefault('TOASTR_NEWS_ON_TOP', 'false')
138 | app.config.setdefault('TOASTR_PROGRESS_BAR', 'true')
139 | app.config.setdefault('TOASTR_OPACITY', True)
140 |
141 | @staticmethod
142 | def context_processor():
143 | return {'toastr': current_app.extensions['toastr']}
144 |
145 | def create(self, timestamp=None):
146 | return current_app.extensions['toastr'](timestamp)
147 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | """
2 | Flask-Toastr
3 | -------------
4 |
5 | Showing non-blocking notifications in Flask templates using toastr.
6 | """
7 | import io
8 | from setuptools import setup
9 |
10 | with io.open('README.md', 'rt', encoding='utf8') as f:
11 | readme = f.read()
12 |
13 | setup(
14 | name='Flask-Toastr',
15 | version='0.5.8',
16 | url='https://github.com/wiltonsr/Flask-Toastr/',
17 | license='MIT',
18 | author='Wilton Rodrigues',
19 | author_email='wiltonsr94@gmail.com',
20 | description='Showing non-blocking notifications in Flask templates using toastr.',
21 | long_description=readme,
22 | long_description_content_type='text/markdown',
23 | py_modules=['flask_toastr'],
24 | zip_safe=False,
25 | include_package_data=True,
26 | platforms='any',
27 | install_requires=[
28 | 'Flask',
29 | 'Jinja2',
30 | ],
31 | classifiers=[
32 | 'Environment :: Web Environment',
33 | 'Intended Audience :: Developers',
34 | 'License :: OSI Approved :: MIT License',
35 | 'Operating System :: OS Independent',
36 | 'Programming Language :: Python',
37 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
38 | 'Topic :: Software Development :: Libraries :: Python Modules'
39 | ]
40 | )
41 |
--------------------------------------------------------------------------------
/tests/test_flask_toastr.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wiltonsr/Flask-Toastr/e79851665913cbd053c8bf7b997654e0014cc200/tests/test_flask_toastr.py
--------------------------------------------------------------------------------