6161 wtf_validators_ = None
6262
6363
64+ @wtf_required
65+ def _setup_strings_common_validators (options : dict , obj : fields .StringField ) -> dict :
66+ """
67+ Extend :attr:`base_options` with common validators for string types.
68+
69+ :param options: dict, usually from :class:`WtfFieldMixin.wtf_generated_options`
70+ :param obj: Any :class:`mongoengine.fields.StringField` subclass instance.
71+ """
72+ assert isinstance (obj , fields .StringField ), "Improperly configured"
73+ if obj .min_length or obj .max_length :
74+ options ["validators" ].insert (
75+ 0 ,
76+ wtf_validators_ .Length (
77+ min = obj .min_length or - 1 ,
78+ max = obj .max_length or - 1 ,
79+ ),
80+ )
81+
82+ if obj .regex :
83+ options ["validators" ].insert (0 , wtf_validators_ .Regexp (regex = obj .regex ))
84+
85+ return options
86+
87+
6488class WtfFieldMixin :
6589 """
6690 Extension wrapper class for mongoengine BaseField.
@@ -469,24 +493,21 @@ class EmailField(WtfFieldMixin, fields.EmailField):
469493 All arguments should be passed as keyword arguments, to exclude unexpected behaviour.
470494
471495 .. versionchanged:: 2.0.0
472- Default field output changed from :class:`.NoneStringField` to
473- :class:`wtforms. fields.EmailField `
496+ Default form field output changed from :class:`.NoneStringField` to
497+ :class:`flask_mongoengine.wtf. fields.MongoEmailField `
474498 """
475499
476- DEFAULT_WTF_FIELD = wtf_fields . EmailField if wtf_fields else None
500+ DEFAULT_WTF_FIELD = custom_fields . MongoEmailField if custom_fields else None
477501
478- def to_wtf_field (
479- self ,
480- * ,
481- model : Optional [Type ] = None ,
482- field_kwargs : Optional [dict ] = None ,
483- ):
484- """
485- Protection from execution of :func:`to_wtf_field` in form generation.
502+ @property
503+ @wtf_required
504+ def wtf_generated_options (self ) -> dict :
505+ """Extend form validators with :class:`wtforms.validators.Email`"""
506+ options = super ().wtf_generated_options
507+ options = _setup_strings_common_validators (options , self )
508+ options ["validators" ].insert (0 , wtf_validators_ .Email ())
486509
487- :raises NotImplementedError: Field converter to WTForm Field not implemented.
488- """
489- raise NotImplementedError ("Field converter to WTForm Field not implemented." )
510+ return options
490511
491512
492513class EmbeddedDocumentField (WtfFieldMixin , fields .EmbeddedDocumentField ):
@@ -1085,22 +1106,112 @@ class StringField(WtfFieldMixin, fields.StringField):
10851106
10861107 For full list of arguments and keyword arguments, look parent field docs.
10871108 All arguments should be passed as keyword arguments, to exclude unexpected behaviour.
1109+
1110+ .. versionchanged:: 2.0.0
1111+ Default form field output changed from :class:`.NoneStringField` to
1112+ :class:`flask_mongoengine.wtf.fields.MongoTextAreaField`
10881113 """
10891114
1090- DEFAULT_WTF_FIELD = wtf_fields . TextAreaField if wtf_fields else None
1115+ DEFAULT_WTF_FIELD = custom_fields . MongoTextAreaField if custom_fields else None
10911116
1092- def to_wtf_field (
1117+ def __init__ (
10931118 self ,
10941119 * ,
1095- model : Optional [Type ] = None ,
1096- field_kwargs : Optional [dict ] = None ,
1120+ password : bool = False ,
1121+ textarea : bool = False ,
1122+ validators : Optional [Union [List , Callable ]] = None ,
1123+ filters : Optional [Union [List , Callable ]] = None ,
1124+ wtf_field_class : Optional [Type ] = None ,
1125+ wtf_filters : Optional [Union [List , Callable ]] = None ,
1126+ wtf_validators : Optional [Union [List , Callable ]] = None ,
1127+ wtf_choices_coerce : Optional [Callable ] = None ,
1128+ wtf_options : Optional [dict ] = None ,
1129+ ** kwargs ,
10971130 ):
10981131 """
1099- Protection from execution of :func:`to_wtf_field` in form generation .
1132+ Extended :func:`__init__` method for mongoengine db field with WTForms options .
11001133
1101- :raises NotImplementedError: Field converter to WTForm Field not implemented.
1134+ :param password:
1135+ DEPRECATED: Force to use :class:`~.MongoPasswordField` for field generation.
1136+ In case of :attr:`password` and :attr:`wtf_field_class` both set, then
1137+ :attr:`wtf_field_class` will be used.
1138+ :param textarea:
1139+ DEPRECATED: Force to use :class:`~.MongoTextAreaField` for field generation.
1140+ In case of :attr:`textarea` and :attr:`wtf_field_class` both set, then
1141+ :attr:`wtf_field_class` will be used.
1142+ :param filters: DEPRECATED: wtf form field filters.
1143+ :param validators: DEPRECATED: wtf form field validators.
1144+ :param wtf_field_class: Any subclass of :class:`wtforms.forms.core.Field` that
1145+ can be used for form field generation. Takes precedence over
1146+ :attr:`DEFAULT_WTF_FIELD` and :attr:`DEFAULT_WTF_CHOICES_FIELD`
1147+ :param wtf_filters: wtf form field filters.
1148+ :param wtf_validators: wtf form field validators.
1149+ :param wtf_choices_coerce: Callable function to replace
1150+ :attr:`DEFAULT_WTF_CHOICES_COERCE` for choices fields.
1151+ :param wtf_options: Dictionary with WTForm Field settings.
1152+ Applied last, takes precedence over any generated field options.
1153+ :param kwargs: keyword arguments silently bypassed to normal mongoengine fields
11021154 """
1103- raise NotImplementedError ("Field converter to WTForm Field not implemented." )
1155+ if password :
1156+ if textarea :
1157+ raise ValueError ("Password field cannot use TextAreaField class." )
1158+
1159+ warnings .warn (
1160+ (
1161+ "Passing 'password' keyword argument to field definition is "
1162+ "deprecated and will be removed in version 3.0.0. "
1163+ "Please use 'wtf_field_class' parameter to specify correct field "
1164+ "class. If both values set, 'wtf_field_class' is used."
1165+ ),
1166+ DeprecationWarning ,
1167+ stacklevel = 2 ,
1168+ )
1169+ wtf_field_class = wtf_field_class or custom_fields .MongoPasswordField
1170+
1171+ if textarea :
1172+ warnings .warn (
1173+ (
1174+ "Passing 'textarea' keyword argument to field definition is "
1175+ "deprecated and will be removed in version 3.0.0. "
1176+ "Please use 'wtf_field_class' parameter to specify correct field "
1177+ "class. If both values set, 'wtf_field_class' is used."
1178+ ),
1179+ DeprecationWarning ,
1180+ stacklevel = 2 ,
1181+ )
1182+ wtf_field_class = wtf_field_class or custom_fields .MongoTextAreaField
1183+
1184+ super ().__init__ (
1185+ validators = validators ,
1186+ filters = filters ,
1187+ wtf_field_class = wtf_field_class ,
1188+ wtf_filters = wtf_filters ,
1189+ wtf_validators = wtf_validators ,
1190+ wtf_choices_coerce = wtf_choices_coerce ,
1191+ wtf_options = wtf_options ,
1192+ ** kwargs ,
1193+ )
1194+
1195+ @property
1196+ def wtf_field_class (self ) -> Type :
1197+ """Parent class overwrite with support of class adjustment by field size."""
1198+ if self ._wtf_field_class :
1199+ return self ._wtf_field_class
1200+ if self .max_length or self .min_length :
1201+ return custom_fields .MongoStringField
1202+ return super ().wtf_field_class
1203+
1204+ @property
1205+ @wtf_required
1206+ def wtf_generated_options (self ) -> dict :
1207+ """
1208+ Extend form validators with :class:`wtforms.validators.Regexp` and
1209+ :class:`wtforms.validators.Length`.
1210+ """
1211+ options = super ().wtf_generated_options
1212+ options = _setup_strings_common_validators (options , self )
1213+
1214+ return options
11041215
11051216
11061217class URLField (WtfFieldMixin , fields .URLField ):
@@ -1109,22 +1220,31 @@ class URLField(WtfFieldMixin, fields.URLField):
11091220
11101221 For full list of arguments and keyword arguments, look parent field docs.
11111222 All arguments should be passed as keyword arguments, to exclude unexpected behaviour.
1223+
1224+ .. versionchanged:: 2.0.0
1225+ Default form field output changed from :class:`.NoneStringField` to
1226+ :class:`~flask_mongoengine.wtf.fields.MongoURLField`
1227+
1228+ .. versionchanged:: 2.0.0
1229+ Now appends :class:`~wtforms.validators.Regexp` and use regexp provided to
1230+ __init__ :attr:`url_regex`, instead of using non-configurable regexp from
1231+ :class:`~wtforms.validators.URL`. This includes configuration conflicts, between
1232+ modules.
11121233 """
11131234
1114- DEFAULT_WTF_FIELD = custom_fields .NoneStringField if custom_fields else None
1235+ DEFAULT_WTF_FIELD = custom_fields .MongoURLField if custom_fields else None
11151236
1116- def to_wtf_field (
1117- self ,
1118- * ,
1119- model : Optional [Type ] = None ,
1120- field_kwargs : Optional [dict ] = None ,
1121- ):
1122- """
1123- Protection from execution of :func:`to_wtf_field` in form generation.
1237+ @property
1238+ @wtf_required
1239+ def wtf_generated_options (self ) -> dict :
1240+ """Extend form validators with :class:`wtforms.validators.Regexp`"""
1241+ options = super ().wtf_generated_options
1242+ options = _setup_strings_common_validators (options , self )
1243+ options ["validators" ].insert (
1244+ 0 , wtf_validators_ .Regexp (regex = self .url_regex , message = "Invalid URL." )
1245+ )
11241246
1125- :raises NotImplementedError: Field converter to WTForm Field not implemented.
1126- """
1127- raise NotImplementedError ("Field converter to WTForm Field not implemented." )
1247+ return options
11281248
11291249
11301250class UUIDField (WtfFieldMixin , fields .UUIDField ):
0 commit comments