Source code for flask_mongoengine.db_fields

"""Responsible for mongoengine fields extension, if WTFForms integration used."""
__all__ = [
    "WtfFieldMixin",
    "BinaryField",
    "BooleanField",
    "CachedReferenceField",
    "ComplexDateTimeField",
    "DateField",
    "DateTimeField",
    "DecimalField",
    "DictField",
    "DynamicField",
    "EmailField",
    "EmbeddedDocumentField",
    "EmbeddedDocumentListField",
    "EnumField",
    "FileField",
    "FloatField",
    "GenericEmbeddedDocumentField",
    "GenericLazyReferenceField",
    "GenericReferenceField",
    "GeoJsonBaseField",
    "GeoPointField",
    "ImageField",
    "IntField",
    "LazyReferenceField",
    "LineStringField",
    "ListField",
    "LongField",
    "MapField",
    "MultiLineStringField",
    "MultiPointField",
    "MultiPolygonField",
    "ObjectIdField",
    "PointField",
    "PolygonField",
    "ReferenceField",
    "SequenceField",
    "SortedListField",
    "StringField",
    "URLField",
    "UUIDField",
]
import decimal
import warnings
from typing import Callable, List, Optional, Type, Union

from bson import ObjectId
from mongoengine import fields

from flask_mongoengine.decorators import wtf_required

try:
    from wtforms import fields as wtf_fields
    from wtforms import validators as wtf_validators_

    from flask_mongoengine.wtf import fields as custom_fields
except ImportError:  # pragma: no cover
    custom_fields = None
    wtf_fields = None
    wtf_validators_ = None


[docs]@wtf_required def _setup_strings_common_validators(options: dict, obj: fields.StringField) -> dict: """ Extend :attr:`base_options` with common validators for string types. :param options: dict, usually from :class:`WtfFieldMixin.wtf_generated_options` :param obj: Any :class:`mongoengine.fields.StringField` subclass instance. """ assert isinstance(obj, fields.StringField), "Improperly configured" if obj.min_length or obj.max_length: options["validators"].insert( 0, wtf_validators_.Length( min=obj.min_length or -1, max=obj.max_length or -1, ), ) if obj.regex: options["validators"].insert(0, wtf_validators_.Regexp(regex=obj.regex)) return options
[docs]@wtf_required def _setup_numbers_common_validators( options: dict, obj: Union[fields.IntField, fields.DecimalField, fields.FloatField] ) -> dict: """ Extend :attr:`base_options` with common validators for number types. :param options: dict, usually from :class:`WtfFieldMixin.wtf_generated_options` :param obj: Any :class:`mongoengine.fields.IntField` or :class:`mongoengine.fields.DecimalField` or :class:`mongoengine.fields.FloatField` subclasses instance. """ assert isinstance( obj, (fields.IntField, fields.DecimalField, fields.FloatField) ), "Improperly configured" if obj.min_value or obj.max_value: options["validators"].insert( 0, wtf_validators_.NumberRange(min=obj.min_value, max=obj.max_value) ) return options
[docs]class WtfFieldMixin: """ Extension wrapper class for mongoengine BaseField. This enables flask-mongoengine wtf to extend the number of field parameters, and settings on behalf of document model form generator for WTForm. **Class variables:** :cvar DEFAULT_WTF_CHOICES_FIELD: Default WTForms Field used for db fields when **choices** option specified. :cvar DEFAULT_WTF_FIELD: Default WTForms Field used for db field. """ DEFAULT_WTF_FIELD = None DEFAULT_WTF_CHOICES_FIELD = wtf_fields.SelectField if wtf_fields else None DEFAULT_WTF_CHOICES_COERCE = str
[docs] def __init__( self, *, validators: Optional[Union[List, Callable]] = None, filters: Optional[Union[List, Callable]] = None, wtf_field_class: Optional[Type] = None, wtf_filters: Optional[Union[List, Callable]] = None, wtf_validators: Optional[Union[List, Callable]] = None, wtf_choices_coerce: Optional[Callable] = None, wtf_options: Optional[dict] = None, **kwargs, ): """ Extended :func:`__init__` method for mongoengine db field with WTForms options. :param filters: DEPRECATED: wtf form field filters. :param validators: DEPRECATED: wtf form field validators. :param wtf_field_class: Any subclass of :class:`wtforms.forms.core.Field` that can be used for form field generation. Takes precedence over :attr:`DEFAULT_WTF_FIELD` and :attr:`DEFAULT_WTF_CHOICES_FIELD` :param wtf_filters: wtf form field filters. :param wtf_validators: wtf form field validators. :param wtf_choices_coerce: Callable function to replace :attr:`DEFAULT_WTF_CHOICES_COERCE` for choices fields. :param wtf_options: Dictionary with WTForm Field settings. Applied last, takes precedence over any generated field options. :param kwargs: keyword arguments silently bypassed to normal mongoengine fields """ if validators is not None: warnings.warn( ( "Passing 'validators' keyword argument to field definition is " "deprecated and will be removed in version 3.0.0. " "Please rename 'validators' to 'wtf_validators'. " "If both values set, 'wtf_validators' is used." ), DeprecationWarning, stacklevel=2, ) if filters is not None: warnings.warn( ( "Passing 'filters' keyword argument to field definition is " "deprecated and will be removed in version 3.0.0. " "Please rename 'filters' to 'wtf_filters'. " "If both values set, 'wtf_filters' is used." ), DeprecationWarning, stacklevel=2, ) self.wtf_validators = self._ensure_callable_or_list( wtf_validators or validators, "wtf_validators" ) self.wtf_filters = self._ensure_callable_or_list( wtf_filters or filters, "wtf_filters" ) self.wtf_options = wtf_options self.wtf_choices_coerce = wtf_choices_coerce or self.DEFAULT_WTF_CHOICES_COERCE # Some attributes that will be updated by super() self.required = False self.default = None self.name = "" self.choices = None # Internals self._wtf_field_class = wtf_field_class super().__init__(**kwargs)
@property def wtf_field_class(self) -> Type: """Final WTForm Field class, that will be used for field generation.""" if self._wtf_field_class: return self._wtf_field_class if self.choices and self.DEFAULT_WTF_CHOICES_FIELD: return self.DEFAULT_WTF_CHOICES_FIELD return self.DEFAULT_WTF_FIELD @property @wtf_required def wtf_generated_options(self) -> dict: """ WTForm Field options generated by class, not updated by user provided :attr:`wtf_options`. """ wtf_field_kwargs: dict = { "label": getattr(self, "verbose_name", self.name), "description": getattr(self, "help_text", None) or "", "default": self.default, # Create a copy of the lists with list() call, since we will be modifying it "validators": list(self.wtf_validators) or [], "filters": list(self.wtf_filters) or [], } if self.required: wtf_field_kwargs["validators"].append(wtf_validators_.InputRequired()) else: wtf_field_kwargs["validators"].append(wtf_validators_.Optional()) if self.choices: wtf_field_kwargs["choices"] = self.choices wtf_field_kwargs["coerce"] = self.wtf_choices_coerce return wtf_field_kwargs @property @wtf_required def wtf_field_options(self) -> dict: """ Final WTForm Field options that will be applied as :attr:`wtf_field_class` kwargs. Can be overwritten by :func:`to_wtf_field` if :func:`~flask_mongoengine.documents.WtfFormMixin.to_wtf_form` called with related field name in :attr:`fields_kwargs`. It is not recommended to overwrite this property, for logic update overwrite :attr:`wtf_generated_options` """ wtf_field_kwargs = self.wtf_generated_options if self.wtf_options is not None: wtf_field_kwargs.update(self.wtf_options) return wtf_field_kwargs
[docs] @staticmethod def _ensure_callable_or_list(argument, msg_flag: str) -> Optional[List]: """ Ensure submitted argument value is a callable object or valid list value. :param argument: Argument input to make verification on. :param msg_flag: Argument string name for error message. """ if argument is None: return [] if callable(argument): return [argument] elif not isinstance(argument, list): raise TypeError(f"Argument '{msg_flag}' must be a list value") return argument
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Default WTFFormField generator for most of the fields. :param model: Document of model from :mod:`~flask_mongoengine.documents`, passed by :func:`~flask_mongoengine.documents.WtfFormMixin.to_wtf_form` for field types with other Document type dependency signature compatibility. :param field_kwargs: Final field generation adjustments, passed for custom Forms generation from :func:`~flask_mongoengine.documents.WtfFormMixin.to_wtf_form` :attr:`fields_kwargs` parameter. """ field_kwargs = field_kwargs or {} wtf_field_kwargs = self.wtf_field_options wtf_field_class = ( field_kwargs.pop("wtf_field_class", None) or self.wtf_field_class ) if field_kwargs: wtf_field_kwargs.update(field_kwargs) return wtf_field_class(**wtf_field_kwargs)
[docs]class BinaryField(WtfFieldMixin, fields.BinaryField): """ Extends :class:`mongoengine.fields.BinaryField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = custom_fields.BinaryField if custom_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class BooleanField(WtfFieldMixin, fields.BooleanField): """ Extends :class:`mongoengine.fields.BooleanField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = custom_fields.MongoBooleanField if custom_fields else None
[docs]class CachedReferenceField(WtfFieldMixin, fields.CachedReferenceField): """ Extends :class:`mongoengine.fields.CachedReferenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class ComplexDateTimeField(WtfFieldMixin, fields.ComplexDateTimeField): """ Extends :class:`mongoengine.fields.ComplexDateTimeField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. .. important:: During WTForm generation this field uses :class:`wtforms.fields.DateTimeLocalField` with milliseconds accuracy. Direct microseconds not supported by browsers for this type of field. If exact microseconds support required, please use :class:`wtforms.fields.DateTimeField` with extended text format set. Examples available in example app. This does not affect on in database accuracy. """ DEFAULT_WTF_FIELD = wtf_fields.DateTimeLocalField if wtf_fields else None @property @wtf_required def wtf_generated_options(self) -> dict: """Extend form date time field with milliseconds support.""" options = super().wtf_generated_options options["format"] = [ "%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%dT%H:%M:%S.%f", ] options["render_kw"] = {"step": "0.000001"} return options
[docs]class DateField(WtfFieldMixin, fields.DateField): """ Extends :class:`mongoengine.fields.DateField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.DateField if wtf_fields else None
[docs]class DateTimeField(WtfFieldMixin, fields.DateTimeField): """ Extends :class:`mongoengine.fields.DateTimeField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.DateTimeLocalField if wtf_fields else None @property @wtf_required def wtf_generated_options(self) -> dict: """Extend form date time field with milliseconds support.""" options = super().wtf_generated_options options["format"] = [ "%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S.%f", "%Y-%m-%dT%H:%M:%S.%f", ] options["render_kw"] = {"step": "1"} return options
[docs]class DecimalField(WtfFieldMixin, fields.DecimalField): """ Extends :class:`mongoengine.fields.DecimalField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.DecimalField if wtf_fields else None DEFAULT_WTF_CHOICES_COERCE = decimal.Decimal @property @wtf_required def wtf_generated_options(self) -> dict: """ Extend form validators with :class:`wtforms.validators.NumberRange`. """ options = super().wtf_generated_options options = _setup_numbers_common_validators(options, self) return options
[docs]class DictField(WtfFieldMixin, fields.DictField): """ Extends :class:`mongoengine.fields.DictField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = custom_fields.MongoDictField if custom_fields else None @property def wtf_generated_options(self) -> dict: """Extends default field options with `null` bypass.""" options = super().wtf_generated_options options["null"] = self.null return options
[docs]class DynamicField(WtfFieldMixin, fields.DynamicField): """ Extends :class:`mongoengine.fields.DynamicField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class EmailField(WtfFieldMixin, fields.EmailField): """ Extends :class:`mongoengine.fields.EmailField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. .. versionchanged:: 2.0.0 Default form field output changed from :class:`.NoneStringField` to :class:`flask_mongoengine.wtf.fields.MongoEmailField` """ DEFAULT_WTF_FIELD = custom_fields.MongoEmailField if custom_fields else None @property @wtf_required def wtf_generated_options(self) -> dict: """Extend form validators with :class:`wtforms.validators.Email`""" options = super().wtf_generated_options options = _setup_strings_common_validators(options, self) options["validators"].insert(0, wtf_validators_.Email()) return options
[docs]class EmbeddedDocumentField(WtfFieldMixin, fields.EmbeddedDocumentField): """ Extends :class:`mongoengine.fields.EmbeddedDocumentField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.FormField if wtf_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class EmbeddedDocumentListField(WtfFieldMixin, fields.EmbeddedDocumentListField): """ Extends :class:`mongoengine.fields.EmbeddedDocumentListField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class EnumField(WtfFieldMixin, fields.EnumField): """ Extends :class:`mongoengine.fields.EnumField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class FileField(WtfFieldMixin, fields.FileField): """ Extends :class:`mongoengine.fields.FileField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.FileField if wtf_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class FloatField(WtfFieldMixin, fields.FloatField): """ Extends :class:`mongoengine.fields.FloatField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. .. versionchanged:: 2.0.0 Default form field output changed from :class:`wtforms.fields.FloatField` to :class:`flask_mongoengine.wtf.fields.MongoFloatField` with 'numbers' input type. """ DEFAULT_WTF_FIELD = custom_fields.MongoFloatField if wtf_fields else None DEFAULT_WTF_CHOICES_COERCE = float @property @wtf_required def wtf_generated_options(self) -> dict: """ Extend form validators with :class:`wtforms.validators.NumberRange`. """ options = super().wtf_generated_options options = _setup_numbers_common_validators(options, self) return options
[docs]class GenericEmbeddedDocumentField(WtfFieldMixin, fields.GenericEmbeddedDocumentField): """ Extends :class:`mongoengine.fields.GenericEmbeddedDocumentField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class GenericLazyReferenceField(WtfFieldMixin, fields.GenericLazyReferenceField): """ Extends :class:`mongoengine.fields.GenericLazyReferenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class GenericReferenceField(WtfFieldMixin, fields.GenericReferenceField): """ Extends :class:`mongoengine.fields.GenericReferenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class GeoJsonBaseField(WtfFieldMixin, fields.GeoJsonBaseField): """ Extends :class:`mongoengine.fields.GeoJsonBaseField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class GeoPointField(WtfFieldMixin, fields.GeoPointField): """ Extends :class:`mongoengine.fields.GeoPointField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class ImageField(WtfFieldMixin, fields.ImageField): """ Extends :class:`mongoengine.fields.ImageField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class IntField(WtfFieldMixin, fields.IntField): """ Extends :class:`mongoengine.fields.IntField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.IntegerField if wtf_fields else None DEFAULT_WTF_CHOICES_COERCE = int @property @wtf_required def wtf_generated_options(self) -> dict: """ Extend form validators with :class:`wtforms.validators.NumberRange`. """ options = super().wtf_generated_options options = _setup_numbers_common_validators(options, self) return options
[docs]class LazyReferenceField(WtfFieldMixin, fields.LazyReferenceField): """ Extends :class:`mongoengine.fields.LazyReferenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class LineStringField(WtfFieldMixin, fields.LineStringField): """ Extends :class:`mongoengine.fields.LineStringField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class ListField(WtfFieldMixin, fields.ListField): """ Extends :class:`mongoengine.fields.ListField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.FieldList if wtf_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class LongField(WtfFieldMixin, fields.LongField): """ Extends :class:`mongoengine.fields.LongField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class MapField(WtfFieldMixin, fields.MapField): """ Extends :class:`mongoengine.fields.MapField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class MultiLineStringField(WtfFieldMixin, fields.MultiLineStringField): """ Extends :class:`mongoengine.fields.MultiLineStringField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class MultiPointField(WtfFieldMixin, fields.MultiPointField): """ Extends :class:`mongoengine.fields.MultiPointField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class MultiPolygonField(WtfFieldMixin, fields.MultiPolygonField): """ Extends :class:`mongoengine.fields.MultiPolygonField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class ObjectIdField(WtfFieldMixin, fields.ObjectIdField): """ Extends :class:`mongoengine.fields.ObjectIdField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_CHOICES_COERCE = ObjectId
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class PointField(WtfFieldMixin, fields.PointField): """ Extends :class:`mongoengine.fields.PointField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class PolygonField(WtfFieldMixin, fields.PolygonField): """ Extends :class:`mongoengine.fields.PolygonField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class ReferenceField(WtfFieldMixin, fields.ReferenceField): """ Extends :class:`mongoengine.fields.ReferenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = custom_fields.ModelSelectField if custom_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class SequenceField(WtfFieldMixin, fields.SequenceField): """ Extends :class:`mongoengine.fields.SequenceField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class SortedListField(WtfFieldMixin, fields.SortedListField): """ Extends :class:`mongoengine.fields.SortedListField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """ DEFAULT_WTF_FIELD = wtf_fields.FieldList if wtf_fields else None
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")
[docs]class StringField(WtfFieldMixin, fields.StringField): """ Extends :class:`mongoengine.fields.StringField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. .. versionchanged:: 2.0.0 Default form field output changed from :class:`.NoneStringField` to :class:`flask_mongoengine.wtf.fields.MongoTextAreaField` """ DEFAULT_WTF_FIELD = custom_fields.MongoTextAreaField if custom_fields else None
[docs] def __init__( self, *, password: bool = False, textarea: bool = False, validators: Optional[Union[List, Callable]] = None, filters: Optional[Union[List, Callable]] = None, wtf_field_class: Optional[Type] = None, wtf_filters: Optional[Union[List, Callable]] = None, wtf_validators: Optional[Union[List, Callable]] = None, wtf_choices_coerce: Optional[Callable] = None, wtf_options: Optional[dict] = None, **kwargs, ): """ Extended :func:`__init__` method for mongoengine db field with WTForms options. :param password: DEPRECATED: Force to use :class:`~.MongoPasswordField` for field generation. In case of :attr:`password` and :attr:`wtf_field_class` both set, then :attr:`wtf_field_class` will be used. :param textarea: DEPRECATED: Force to use :class:`~.MongoTextAreaField` for field generation. In case of :attr:`textarea` and :attr:`wtf_field_class` both set, then :attr:`wtf_field_class` will be used. :param filters: DEPRECATED: wtf form field filters. :param validators: DEPRECATED: wtf form field validators. :param wtf_field_class: Any subclass of :class:`wtforms.forms.core.Field` that can be used for form field generation. Takes precedence over :attr:`DEFAULT_WTF_FIELD` and :attr:`DEFAULT_WTF_CHOICES_FIELD` :param wtf_filters: wtf form field filters. :param wtf_validators: wtf form field validators. :param wtf_choices_coerce: Callable function to replace :attr:`DEFAULT_WTF_CHOICES_COERCE` for choices fields. :param wtf_options: Dictionary with WTForm Field settings. Applied last, takes precedence over any generated field options. :param kwargs: keyword arguments silently bypassed to normal mongoengine fields """ if password: if textarea: raise ValueError("Password field cannot use TextAreaField class.") warnings.warn( ( "Passing 'password' keyword argument to field definition is " "deprecated and will be removed in version 3.0.0. " "Please use 'wtf_field_class' parameter to specify correct field " "class. If both values set, 'wtf_field_class' is used." ), DeprecationWarning, stacklevel=2, ) wtf_field_class = wtf_field_class or custom_fields.MongoPasswordField if textarea: warnings.warn( ( "Passing 'textarea' keyword argument to field definition is " "deprecated and will be removed in version 3.0.0. " "Please use 'wtf_field_class' parameter to specify correct field " "class. If both values set, 'wtf_field_class' is used." ), DeprecationWarning, stacklevel=2, ) wtf_field_class = wtf_field_class or custom_fields.MongoTextAreaField super().__init__( validators=validators, filters=filters, wtf_field_class=wtf_field_class, wtf_filters=wtf_filters, wtf_validators=wtf_validators, wtf_choices_coerce=wtf_choices_coerce, wtf_options=wtf_options, **kwargs, )
@property def wtf_field_class(self) -> Type: """Parent class overwrite with support of class adjustment by field size.""" if self._wtf_field_class: return self._wtf_field_class if self.max_length or self.min_length: return custom_fields.MongoStringField return super().wtf_field_class @property @wtf_required def wtf_generated_options(self) -> dict: """ Extend form validators with :class:`wtforms.validators.Regexp` and :class:`wtforms.validators.Length`. """ options = super().wtf_generated_options options = _setup_strings_common_validators(options, self) return options
[docs]class URLField(WtfFieldMixin, fields.URLField): """ Extends :class:`mongoengine.fields.URLField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. .. versionchanged:: 2.0.0 Default form field output changed from :class:`.NoneStringField` to :class:`~flask_mongoengine.wtf.fields.MongoURLField` .. versionchanged:: 2.0.0 Now appends :class:`~wtforms.validators.Regexp` and use regexp provided to __init__ :attr:`url_regex`, instead of using non-configurable regexp from :class:`~wtforms.validators.URL`. This includes configuration conflicts, between modules. """ DEFAULT_WTF_FIELD = custom_fields.MongoURLField if custom_fields else None @property @wtf_required def wtf_generated_options(self) -> dict: """Extend form validators with :class:`wtforms.validators.Regexp`""" options = super().wtf_generated_options options = _setup_strings_common_validators(options, self) options["validators"].insert( 0, wtf_validators_.Regexp(regex=self.url_regex, message="Invalid URL.") ) return options
[docs]class UUIDField(WtfFieldMixin, fields.UUIDField): """ Extends :class:`mongoengine.fields.UUIDField` with wtf required parameters. For full list of arguments and keyword arguments, look parent field docs. All arguments should be passed as keyword arguments, to exclude unexpected behaviour. """
[docs] def to_wtf_field( self, *, model: Optional[Type] = None, field_kwargs: Optional[dict] = None, ): """ Protection from execution of :func:`to_wtf_field` in form generation. :raises NotImplementedError: Field converter to WTForm Field not implemented. """ raise NotImplementedError("Field converter to WTForm Field not implemented.")