{"id":14065234,"url":"https://github.com/christabor/flask_extras","last_synced_at":"2025-04-12T12:51:58.170Z","repository":{"id":57430294,"uuid":"52041586","full_name":"christabor/flask_extras","owner":"christabor","description":"Assorted generic flask views, blueprints, Jinja2 filters, macros, forms and more.","archived":false,"fork":false,"pushed_at":"2019-11-04T01:48:58.000Z","size":869,"stargazers_count":24,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T07:36:29.463Z","etag":null,"topics":["filter","flask-views","html","jinja2","jinja2-filters","jinja2-templates","macros"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/christabor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-18T21:54:05.000Z","updated_at":"2024-05-12T04:06:29.000Z","dependencies_parsed_at":"2022-08-26T04:43:35.950Z","dependency_job_id":null,"html_url":"https://github.com/christabor/flask_extras","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christabor%2Fflask_extras","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christabor%2Fflask_extras/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christabor%2Fflask_extras/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christabor%2Fflask_extras/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/christabor","download_url":"https://codeload.github.com/christabor/flask_extras/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248571531,"owners_count":21126518,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filter","flask-views","html","jinja2","jinja2-filters","jinja2-templates","macros"],"created_at":"2024-08-13T07:04:22.867Z","updated_at":"2025-04-12T12:51:58.148Z","avatar_url":"https://github.com/christabor.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"[![Codacy Badge](https://api.codacy.com/project/badge/Grade/1f8f45e92a9b4ed1ab5029ee7a0e5534)](https://www.codacy.com/app/dxdstudio/flask_extras?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=christabor/flask_extras\u0026utm_campaign=badger)\n[![Build Status](https://travis-ci.org/christabor/flask_extras.svg?branch=master)](https://travis-ci.org/christabor/flask_extras)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/christabor/flask_extras/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/christabor/flask_extras/?branch=master)\n[![Code Climate](https://codeclimate.com/github/christabor/flask_extras/badges/gpa.svg)](https://codeclimate.com/github/christabor/flask_extras)\n[![Coverage Status](https://coveralls.io/repos/github/christabor/flask_extras/badge.svg?branch=master)](https://coveralls.io/github/christabor/flask_extras?branch=master)\n[![Code Health](https://landscape.io/github/christabor/flask_extras/master/landscape.svg?style=flat)](https://landscape.io/github/christabor/flask_extras/master)\n\n# Flask Extras\nAssorted useful flask views, blueprints, Jinja2 template filters, and templates/macros.\n\n## Overall setup\n\nAs of `3.4.0`, filters and templates will automatically be registered and available through the following simple command:\n\n```python\nfrom flask_extras import FlaskExtras\napp = Flask('myapp')\nFlaskExtras(app)\n```\n\nFor the old way, check out [this page](wiki/old_setup.md)\n\n## Available features\n\n### Views\n\nImport them like usual:\n\n```python\nfrom flask_extras.views import (\n    statuses,\n)\n```\n\n*Note:* each view must have a valid template in your apps templates dir. See each view for the required names and locations.\n\n*Note:* each view has configuration helpers to inject or configure your app. See source for details.\n\n### Macros\n\nAll macro DEMOS are available by cloning this repo and firing up the flask test server, e.g:\n\n```shell\ngit clone https://github.com/christabor/flask_extras\ncd flask_extras\nvirtualenv env\nsource env/bin/active\npython setup.py install\ncd test_app\npython app.py\nopen http://localhost:5014\n```\n\n#### Philosophy\n\nMany macros leverage the structure of data to find a common mapping. For example, a dictionary looks a lot like a definition list (dl), and a list looks really like a ...list, in html terms. But stepping even further into things, more complex data structures can have fairly elegant mappings when using macros to hide away a lot of html cruft.\n\nThis makes rendering complex server side data easy, without having to do lots of transformation. This won't work for cases where every last DOM element need to be stylized, but many users will find incredibly powerful tools available to make UI development much easier.\n\n**Many more macros** are available. You can use them like so:\n\n```html\n{% from 'macros.html' import list_group, objects2table %}\n```\n\nFor the most comprehensive docs, check out each [macro](flask_extras/macros/). Comment \"docstrings\" are inline using jinja2 comments (these are not rendered in your html).\n\nAlso, check the source and/or output to see what classes are available for style overrides.\n\n### Statuses\n\nProvides views for common status codes. Usage:\n\n```python\napp = statuses.inject_error_views(app)\n```\n\nSee source for more.\n\n### Decorators\n\nSee the source for more. Usage example:\n\n```python\nfrom flask_extras.decorators import require_headers\n\napp.route('/')\n@require_headers(['X-Foo'])\ndef foo():\n    pass\n```\n\n\n### Forms\n\n#### WTForm Multi-step wizard\n\nA WTForm extension for handling an arbitrary number of separate forms as a single, multi-step, multi-POST wizard. All state and data are handled by apps' session backend. Building forms is just like you're used to -- simple and intuitive. Just inherit the `MultiStepWizard` class and put a `__forms__` key on it, which is just a list of all the forms you want to use. *Note*: list order matters for your form steps.\n\nUsage example:\n\n```python\nfrom flask.ext.wtf import FlaskForm\n\nfrom flask_extras.forms.wizard import MultiStepWizard\n\n\nclass MultiStepTest1(FlaskForm):\n    field1 = StringField(validators=[validators.DataRequired()],)\n    field2 = IntegerField(validators=[validators.DataRequired()],)\n\n\nclass MultiStepTest2(FlaskForm):\n    field3 = StringField(validators=[validators.DataRequired()],)\n    field4 = IntegerField(validators=[validators.DataRequired()],)\n\n\nclass MyCoolForm(MultiStepWizard):\n    __forms__ = [\n        MultiStepTest1,\n        MultiStepTest2,\n    ]\n```\n\nand an example route:\n\n```python\nfrom forms import MyCoolForm\n\n@app.route('/', methods=['GET', 'POST'])\ndef index():\n    curr_step = request.args.get('curr_step')\n    form_kwargs = dict(session_key='mycustomkey')\n    if curr_step is not None:\n        form_kwargs.update(curr_step=curr_step)\n    form = forms.MyCoolForm(**form_kwargs)\n    kwargs = dict(form=form)\n    if request.method == 'POST':\n        if form.validate_on_submit():\n            if form.is_complete():\n                data = form.alldata(combine_fields=True, flush_after=True)\n                flash('Form validated and complete! data = {}'.format(data),\n                      'success')\n                return jsonify(data)\n            else:\n                flash('Great job, but not done yet ({} steps remain!).'.format(form.remaining))\n        else:\n            flash('Invalid form data.', 'error')\n    return render_template('index.html', **kwargs)\n```\n\nand an example html page (using the [wtform_form](flask_extras/macros/macros.html) macro also available):\n\n```html\n{% if form.is_complete() %}\n    \u003cspan class=\"well\"\u003eComplete!\u003c/span\u003e\n{% else %}\n    \u003cul class=\"list-inline\"\u003e\n        {% for step in form.steps %}\n            \u003cli\u003e\n                {% if step == form.curr_step %}\n                    \u003cstrong class=\"lead label label-info\"\u003ecurrent {{ step }}\u003c/strong\u003e\n                {% else %}\n                    \u003ca href=\"{{ url_for('app.index') }}?curr_step={{ step }}\"\u003e{{ step }}\u003c/a\u003e\n                {% endif %}\n                {% if not loop.last %}\n                    \u0026nbsp;\u0026nbsp;/\n                {% endif %}\n            \u003c/li\u003e\n        {% endfor %}\n    \u003c/ul\u003e\n    {{ wtform_form(form,\n        classes=['form', 'form-horizontal'],\n        btn_classes=['btn btn-primary', 'btn-lg'],\n        align='right',\n        action=url_for('app.index'),\n        method='POST',\n        reset_btn=False,\n        horizontal=True,\n    ) }}\n{% endif %}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristabor%2Fflask_extras","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchristabor%2Fflask_extras","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristabor%2Fflask_extras/lists"}