Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/flask_wtf/form.py: 52%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from flask import current_app
2from flask import request
3from flask import session
4from markupsafe import Markup
5from werkzeug.datastructures import CombinedMultiDict
6from werkzeug.datastructures import ImmutableMultiDict
7from werkzeug.utils import cached_property
8from wtforms import Form
9from wtforms.meta import DefaultMeta
10from wtforms.widgets import HiddenInput
12from .csrf import _FlaskFormCSRF
14try:
15 from .i18n import translations
16except ImportError:
17 translations = None # babel not installed
20SUBMIT_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
21_Auto = object()
24class FlaskForm(Form):
25 """Flask-specific subclass of WTForms :class:`~wtforms.form.Form`.
27 If ``formdata`` is not specified, this will use :attr:`flask.request.form`
28 and :attr:`flask.request.files`. Explicitly pass ``formdata=None`` to
29 prevent this.
30 """
32 class Meta(DefaultMeta):
33 csrf_class = _FlaskFormCSRF
34 csrf_context = session # not used, provided for custom csrf_class
36 @cached_property
37 def csrf(self):
38 return current_app.config.get("WTF_CSRF_ENABLED", True)
40 @cached_property
41 def csrf_secret(self):
42 return current_app.config.get("WTF_CSRF_SECRET_KEY", current_app.secret_key)
44 @cached_property
45 def csrf_field_name(self):
46 return current_app.config.get("WTF_CSRF_FIELD_NAME", "csrf_token")
48 @cached_property
49 def csrf_time_limit(self):
50 return current_app.config.get("WTF_CSRF_TIME_LIMIT", 3600)
52 def wrap_formdata(self, form, formdata):
53 if formdata is _Auto:
54 if _is_submitted():
55 if request.files:
56 return CombinedMultiDict((request.files, request.form))
57 elif request.form:
58 return request.form
59 elif request.is_json:
60 return ImmutableMultiDict(request.get_json())
62 return None
64 return formdata
66 def get_translations(self, form):
67 if not current_app.config.get("WTF_I18N_ENABLED", True):
68 return super().get_translations(form)
70 return translations
72 def __init__(self, formdata=_Auto, **kwargs):
73 super().__init__(formdata=formdata, **kwargs)
75 def is_submitted(self):
76 """Consider the form submitted if there is an active request and
77 the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
78 """
80 return _is_submitted()
82 def validate_on_submit(self, extra_validators=None):
83 """Call :meth:`validate` only if the form is submitted.
84 This is a shortcut for ``form.is_submitted() and form.validate()``.
85 """
86 return self.is_submitted() and self.validate(extra_validators=extra_validators)
88 def hidden_tag(self, *fields):
89 """Render the form's hidden fields in one call.
91 A field is considered hidden if it uses the
92 :class:`~wtforms.widgets.HiddenInput` widget.
94 If ``fields`` are given, only render the given fields that
95 are hidden. If a string is passed, render the field with that
96 name if it exists.
98 .. versionchanged:: 0.13
100 No longer wraps inputs in hidden div.
101 This is valid HTML 5.
103 .. versionchanged:: 0.13
105 Skip passed fields that aren't hidden.
106 Skip passed names that don't exist.
107 """
109 def hidden_fields(fields):
110 for f in fields:
111 if isinstance(f, str):
112 f = getattr(self, f, None)
114 if f is None or not isinstance(f.widget, HiddenInput):
115 continue
117 yield f
119 return Markup("\n".join(str(f) for f in hidden_fields(fields or self)))
122def _is_submitted():
123 """Consider the form submitted if there is an active request and
124 the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
125 """
127 return bool(request) and request.method in SUBMIT_METHODS