PCv5/venv/Lib/site-packages/flask_wtf/form.py

159 lines
4.8 KiB
Python

import warnings
from flask import current_app, request
from flask import session
from jinja2 import Markup
from werkzeug.datastructures import CombinedMultiDict, ImmutableMultiDict
from werkzeug.utils import cached_property
from wtforms import Form
from wtforms.meta import DefaultMeta
from wtforms.widgets import HiddenInput
from ._compat import FlaskWTFDeprecationWarning, string_types, text_type
from .csrf import _FlaskFormCSRF
try:
from .i18n import translations
except ImportError:
translations = None # babel not installed
SUBMIT_METHODS = set(('POST', 'PUT', 'PATCH', 'DELETE'))
_Auto = object()
class FlaskForm(Form):
"""Flask-specific subclass of WTForms :class:`~wtforms.form.Form`.
If ``formdata`` is not specified, this will use :attr:`flask.request.form`
and :attr:`flask.request.files`. Explicitly pass ``formdata=None`` to
prevent this.
"""
class Meta(DefaultMeta):
csrf_class = _FlaskFormCSRF
csrf_context = session # not used, provided for custom csrf_class
@cached_property
def csrf(self):
return current_app.config.get('WTF_CSRF_ENABLED', True)
@cached_property
def csrf_secret(self):
return current_app.config.get(
'WTF_CSRF_SECRET_KEY', current_app.secret_key
)
@cached_property
def csrf_field_name(self):
return current_app.config.get('WTF_CSRF_FIELD_NAME', 'csrf_token')
@cached_property
def csrf_time_limit(self):
return current_app.config.get('WTF_CSRF_TIME_LIMIT', 3600)
def wrap_formdata(self, form, formdata):
if formdata is _Auto:
if _is_submitted():
if request.files:
return CombinedMultiDict((
request.files, request.form
))
elif request.form:
return request.form
elif request.get_json():
return ImmutableMultiDict(request.get_json())
return None
return formdata
def get_translations(self, form):
if not current_app.config.get('WTF_I18N_ENABLED', True):
return None
return translations
def __init__(self, formdata=_Auto, **kwargs):
csrf_enabled = kwargs.pop('csrf_enabled', None)
if csrf_enabled is not None:
warnings.warn(FlaskWTFDeprecationWarning(
'"csrf_enabled" is deprecated and will be removed in 1.0. '
'Set "meta.csrf" instead.'
), stacklevel=3)
kwargs['meta'] = kwargs.get('meta') or {}
kwargs['meta'].setdefault('csrf', csrf_enabled)
super(FlaskForm, self).__init__(formdata=formdata, **kwargs)
def is_submitted(self):
"""Consider the form submitted if there is an active request and
the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
"""
return _is_submitted()
def validate_on_submit(self):
"""Call :meth:`validate` only if the form is submitted.
This is a shortcut for ``form.is_submitted() and form.validate()``.
"""
return self.is_submitted() and self.validate()
def hidden_tag(self, *fields):
"""Render the form's hidden fields in one call.
A field is considered hidden if it uses the
:class:`~wtforms.widgets.HiddenInput` widget.
If ``fields`` are given, only render the given fields that
are hidden. If a string is passed, render the field with that
name if it exists.
.. versionchanged:: 0.13
No longer wraps inputs in hidden div.
This is valid HTML 5.
.. versionchanged:: 0.13
Skip passed fields that aren't hidden.
Skip passed names that don't exist.
"""
def hidden_fields(fields):
for f in fields:
if isinstance(f, string_types):
f = getattr(self, f, None)
if f is None or not isinstance(f.widget, HiddenInput):
continue
yield f
return Markup(
u'\n'.join(text_type(f) for f in hidden_fields(fields or self))
)
def _is_submitted():
"""Consider the form submitted if there is an active request and
the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
"""
return bool(request) and request.method in SUBMIT_METHODS
class Form(FlaskForm):
"""
.. deprecated:: 0.13
Renamed to :class:`~flask_wtf.FlaskForm`.
"""
def __init__(self, *args, **kwargs):
warnings.warn(FlaskWTFDeprecationWarning(
'"flask_wtf.Form" has been renamed to "FlaskForm" '
'and will be removed in 1.0.'
), stacklevel=3)
super(Form, self).__init__(*args, **kwargs)