def get_form( model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, allow_pk=False, extra_fields=None, ): """ Create form from peewee model and contribute extra fields, if necessary """ result = model_form( model, base_class=base_class, only=only, exclude=exclude, field_args=field_args, allow_pk=allow_pk, converter=converter, ) if extra_fields: for name, field in iteritems(extra_fields): setattr(result, name, form.recreate_field(field)) return result
def convert(self, model, field, field_args): # Check if it is overridden field if isinstance(field, FieldPlaceholder): return form.recreate_field(field.field) kwargs = { 'label': getattr(field, 'verbose_name', None), 'description': getattr(field, 'help_text', ''), 'validators': [], 'filters': [], 'default': field.default } if field_args: kwargs.update(field_args) if kwargs['validators']: # Create a copy of the list since we will be modifying it. kwargs['validators'] = list(kwargs['validators']) if field.required: kwargs['validators'].append(validators.InputRequired()) elif not isinstance(field, ListField): kwargs['validators'].append(validators.Optional()) ftype = type(field).__name__ override = self._get_field_override(field.name) if field.choices: kwargs['choices'] = list(self._convert_choices(field.choices)) if override: return self._return_override(override, field, kwargs) if ftype == "LPStringField": return self.converters[ftype](model, field, kwargs) if ftype in self.converters: kwargs["coerce"] = self.coerce(ftype) if kwargs.pop('multiple', False): return fields.SelectMultipleField(**kwargs) return fields.SelectField(**kwargs) if hasattr(field, 'to_form_field'): return field.to_form_field(model, kwargs) if override: if hasattr(field, "html_attrs"): kwargs["html_attrs"] = field.html_attrs return self._return_override(override, field, kwargs) if ftype in self.converters: return self.converters[ftype](model, field, kwargs)
def convert(self, model, field, field_args): # Check if it is overridden field if isinstance(field, FieldPlaceholder): return form.recreate_field(field.field) kwargs = { 'label': getattr(field, 'verbose_name', None), 'description': getattr(field, 'help_text', ''), 'validators': [], 'filters': [], 'default': field.default } if field_args: kwargs.update(field_args) if kwargs['validators']: # Create a copy of the list since we will be modifying it. kwargs['validators'] = list(kwargs['validators']) if field.required: if isinstance(field, ListField): kwargs['validators'].append(FieldListInputRequired()) else: kwargs['validators'].append(validators.InputRequired()) elif not isinstance(field, ListField): kwargs['validators'].append(validators.Optional()) ftype = type(field).__name__ if field.choices: kwargs['choices'] = list(self._convert_choices(field.choices)) if ftype in self.converters: kwargs["coerce"] = self.coerce(ftype) if kwargs.pop('multiple', False): return fields.SelectMultipleField(**kwargs) return fields.SelectField(**kwargs) ftype = type(field).__name__ if hasattr(field, 'to_form_field'): return field.to_form_field(model, kwargs) override = self._get_field_override(field.name) if override: return override(**kwargs) if ftype in self.converters: return self.converters[ftype](model, field, kwargs)
def convert(self, model, field, field_args): # Check if it is overridden field if isinstance(field, FieldPlaceholder): return form.recreate_field(field.field) kwargs = { "label": getattr(field, "verbose_name", None), "description": getattr(field, "help_text", ""), "validators": [], "filters": [], "default": field.default, } if field_args: kwargs.update(field_args) if kwargs["validators"]: # Create a copy of the list since we will be modifying it. kwargs["validators"] = list(kwargs["validators"]) if field.required: kwargs["validators"].append(validators.InputRequired()) elif not isinstance(field, ListField): kwargs["validators"].append(validators.Optional()) ftype = type(field).__name__ if field.choices: kwargs["choices"] = list(self._convert_choices(field.choices)) if ftype in self.converters: kwargs["coerce"] = self.coerce(ftype) if kwargs.pop("multiple", False): return fields.SelectMultipleField(**kwargs) return fields.SelectField(**kwargs) ftype = type(field).__name__ if hasattr(field, "to_form_field"): return field.to_form_field(model, kwargs) override = self._get_field_override(field.name) if override: return override(**kwargs) if ftype in self.converters: return self.converters[ftype](model, field, kwargs)
def convert(self, model, field, field_args): # Check if it is overridden field if isinstance(field, FieldPlaceholder): return form.recreate_field(field.field) kwargs = { 'label': getattr(field, 'verbose_name', field.name), 'description': getattr(field, 'help_text', ''), 'validators': [], 'filters': [], 'default': field.default } if field_args: # prevent modification of self.form_args kwargs.update(deepcopy(field_args)) if field.required: kwargs['validators'].append(validators.InputRequired()) elif not isinstance(field, ListField): kwargs['validators'].append(validators.Optional()) ftype = type(field).__name__ if field.choices: kwargs['choices'] = list(self._convert_choices(field.choices)) if ftype in self.converters: kwargs["coerce"] = self.coerce(ftype) if kwargs.pop('multiple', False): return fields.SelectMultipleField(**kwargs) return fields.SelectField(**kwargs) ftype = type(field).__name__ if hasattr(field, 'to_form_field'): return field.to_form_field(model, kwargs) override = self._get_field_override(field.name) if override: return override(**kwargs) if ftype in self.converters: return self.converters[ftype](model, field, kwargs)
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, extra_fields=None): field_args = field_args or {} # Find properties properties = sorted(((v.name, v) for v in model._meta.fields)) if only: props = dict(properties) def find(name): if extra_fields and name in extra_fields: return FieldPlaceholder(extra_fields[name]) p = props.get(name) if p is not None: return p raise ValueError('Invalid model property name %s.%s' % (model, name)) properties = ((p, find(p)) for p in only) elif exclude: properties = (p for p in properties if p[0] not in exclude) # Create fields field_dict = {} for name, p in properties: field = converter.convert(model, p, field_args.get(name)) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) field_dict['model_class'] = model return type(model.__name__ + 'Form', (base_class,), field_dict)
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, allow_pk=False, extra_fields=None): """ Create form from peewee model and contribute extra fields, if necessary """ result = model_form(model, base_class=base_class, only=only, exclude=exclude, field_args=field_args, allow_pk=allow_pk, converter=converter) if extra_fields: for name, field in iteritems(extra_fields): setattr(result, name, form.recreate_field(field)) return result
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, extra_fields=None): """ Create a wtforms Form for a given mongoengine Document schema:: from flask_mongoengine.wtf import model_form from myproject.myapp.schemas import Article ArticleForm = model_form(Article) :param model: A mongoengine Document schema class :param base_class: Base form class to extend from. Must be a ``wtforms.Form`` subclass. :param only: An optional iterable with the property names that should be included in the form. Only these properties will have fields. :param exclude: An optional iterable with the property names that should be excluded from the form. All other properties will have fields. :param field_args: An optional dictionary of field names mapping to keyword arguments used to construct each field object. :param converter: A converter to generate the fields based on the model properties. If not set, ``ModelConverter`` is used. """ if isinstance(model, str): model = get_document(model) if not isinstance(model, (BaseDocument, DocumentMetaclass)): raise TypeError('Model must be a mongoengine Document schema') field_args = field_args or {} # Find properties properties = sorted(((k, v) for k, v in iteritems(model._fields)), key=lambda v: v[1].creation_counter) if only: props = dict(properties) def find(name): if extra_fields and name in extra_fields: return FieldPlaceholder(extra_fields[name]) p = props.get(name) if p is not None: return p raise ValueError('Invalid model property name %s.%s' % (model, name)) properties = ((p, find(p)) for p in only) elif exclude: properties = (p for p in properties if p[0] not in exclude) # Create fields field_dict = {} for name, p in properties: field = converter.convert(model, p, field_args.get(name)) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) field_dict['model_class'] = model return type(model.__name__ + 'Form', (base_class,), field_dict)
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, hidden_pk=False, ignore_hidden=True, extra_fields=None): """ Generate form from the model. :param model: Model to generate form from :param converter: Converter class to use :param base_class: Base form class :param only: Include fields :param exclude: Exclude fields :param field_args: Dictionary with additional field arguments :param hidden_pk: Generate hidden field with model primary key or not :param ignore_hidden: If set to True (default), will ignore properties that start with underscore """ # TODO: Support new 0.8 API if not hasattr(model, '_sa_class_manager'): raise TypeError('model must be a sqlalchemy mapped model') mapper = model._sa_class_manager.mapper field_args = field_args or {} properties = ((p.key, p) for p in mapper.iterate_properties) if only: def find(name): # If field is in extra_fields, it has higher priority if extra_fields and name in extra_fields: return name, FieldPlaceholder(extra_fields[name]) column, path = get_field_with_path(model, name, return_remote_proxy_attr=False) if path and not (is_relationship(column) or is_association_proxy(column)): raise Exception("form column is located in another table and " "requires inline_models: {0}".format(name)) if is_association_proxy(column): return name, column relation_name = column.key if column is not None and hasattr(column, 'property'): return relation_name, column.property raise ValueError('Invalid model property name %s.%s' % (model, name)) # Filter properties while maintaining property order in 'only' list properties = (find(x) for x in only) elif exclude: properties = (x for x in properties if x[0] not in exclude) field_dict = {} for name, p in properties: # Ignore protected properties if ignore_hidden and name.startswith('_'): continue prop = _resolve_prop(p) field = converter.convert(model, mapper, name, prop, field_args.get(name), hidden_pk) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) return type(model.__name__ + 'Form', (base_class, ), field_dict)
def convert(self, model, mapper, name, prop, field_args, hidden_pk): # Properly handle forced fields if isinstance(prop, FieldPlaceholder): return form.recreate_field(prop.field) kwargs = {'validators': [], 'filters': []} if field_args: kwargs.update(field_args) if kwargs['validators']: # Create a copy of the list since we will be modifying it. kwargs['validators'] = list(kwargs['validators']) # Check if it is relation or property if hasattr(prop, 'direction') or is_association_proxy(prop): property_is_association_proxy = is_association_proxy(prop) if property_is_association_proxy: if not hasattr(prop.remote_attr, 'prop'): raise Exception( 'Association proxy referencing another association proxy is not supported.' ) prop = prop.remote_attr.prop return self._convert_relation(name, prop, property_is_association_proxy, kwargs) elif hasattr(prop, 'columns'): # Ignore pk/fk # Check if more than one column mapped to the property if len(prop.columns) > 1: columns = filter_foreign_columns(model.__table__, prop.columns) if len(columns) > 1: warnings.warn( 'Can not convert multiple-column properties (%s.%s)' % (model, prop.key)) return None column = columns[0] else: # Grab column column = prop.columns[0] form_columns = getattr(self.view, 'form_columns', None) or () # Do not display foreign keys - use relations, except when explicitly instructed if column.foreign_keys and prop.key not in form_columns: return None # Only display "real" columns if not isinstance(column, Column): return None unique = False if column.primary_key: if hidden_pk: # If requested to add hidden field, show it return fields.HiddenField() else: # By default, don't show primary keys either # If PK is not explicitly allowed, ignore it if prop.key not in form_columns: return None # Current Unique Validator does not work with multicolumns-pks if not has_multiple_pks(model): kwargs['validators'].append( Unique(self.session, model, column)) unique = True # If field is unique, validate it if column.unique and not unique: kwargs['validators'].append(Unique(self.session, model, column)) optional_types = getattr(self.view, 'form_optional_types', (Boolean, )) if (not column.nullable and not isinstance(column.type, optional_types) and not column.default and not column.server_default): kwargs['validators'].append(validators.InputRequired()) # Apply label and description if it isn't inline form field if self.view.model == mapper.class_: kwargs['label'] = self._get_label(prop.key, kwargs) kwargs['description'] = self._get_description(prop.key, kwargs) # Figure out default value default = getattr(column, 'default', None) value = None if default is not None: value = getattr(default, 'arg', None) if value is not None: if getattr(default, 'is_callable', False): value = lambda: default.arg(None) # noqa: E731 else: if not getattr(default, 'is_scalar', True): value = None if value is not None: kwargs['default'] = value # Check nullable if column.nullable: kwargs['validators'].append(validators.Optional()) # Override field type if necessary override = self._get_field_override(prop.key) if override: return override(**kwargs) # Check choices form_choices = getattr(self.view, 'form_choices', None) if mapper.class_ == self.view.model and form_choices: choices = form_choices.get(prop.key) if choices: return form.Select2Field(choices=choices, allow_blank=column.nullable, **kwargs) # Run converter converter = self.get_converter(column) if converter is None: return None return converter(model=model, mapper=mapper, prop=prop, column=column, field_args=kwargs) return None
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, hidden_pk=False, ignore_hidden=True, extra_fields=None): """ Generate form from the model. :param model: Model to generate form from :param converter: Converter class to use :param base_class: Base form class :param only: Include fields :param exclude: Exclude fields :param field_args: Dictionary with additional field arguments :param hidden_pk: Generate hidden field with model primary key or not :param ignore_hidden: If set to True (default), will ignore properties that start with underscore """ # TODO: Support new 0.8 API if not hasattr(model, '_sa_class_manager'): raise TypeError('model must be a sqlalchemy mapped model') mapper = model._sa_class_manager.mapper field_args = field_args or {} properties = ((p.key, p) for p in mapper.iterate_properties) if only: def find(name): # If field is in extra_fields, it has higher priority if extra_fields and name in extra_fields: return name, FieldPlaceholder(extra_fields[name]) column, path = get_field_with_path(model, name) if path and not hasattr(column.prop, 'direction'): raise Exception("form column is located in another table and " "requires inline_models: {0}".format(name)) name = column.key if column is not None and hasattr(column, 'property'): return name, column.property raise ValueError('Invalid model property name %s.%s' % (model, name)) # Filter properties while maintaining property order in 'only' list properties = (find(x) for x in only) elif exclude: properties = (x for x in properties if x[0] not in exclude) field_dict = {} for name, p in properties: # Ignore protected properties if ignore_hidden and name.startswith('_'): continue prop = _resolve_prop(p) field = converter.convert(model, mapper, prop, field_args.get(name), hidden_pk) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) return type(model.__name__ + 'Form', (base_class, ), field_dict)
def convert(self, model, mapper, prop, field_args, hidden_pk): # Properly handle forced fields if isinstance(prop, FieldPlaceholder): return form.recreate_field(prop.field) kwargs = { 'validators': [], 'filters': [] } if field_args: kwargs.update(field_args) if kwargs['validators']: # Create a copy of the list since we will be modifying it. kwargs['validators'] = list(kwargs['validators']) # Check if it is relation or property if hasattr(prop, 'direction'): return self._convert_relation(prop, kwargs) elif hasattr(prop, 'columns'): # Ignore pk/fk # Check if more than one column mapped to the property if len(prop.columns) > 1: columns = filter_foreign_columns(model.__table__, prop.columns) if len(columns) > 1: warnings.warn('Can not convert multiple-column properties (%s.%s)' % (model, prop.key)) return None column = columns[0] else: # Grab column column = prop.columns[0] form_columns = getattr(self.view, 'form_columns', None) or () # Do not display foreign keys - use relations, except when explicitly instructed if column.foreign_keys and prop.key not in form_columns: return None # Only display "real" columns if not isinstance(column, Column): return None unique = False if column.primary_key: if hidden_pk: # If requested to add hidden field, show it return fields.HiddenField() else: # By default, don't show primary keys either # If PK is not explicitly allowed, ignore it if prop.key not in form_columns: return None # Current Unique Validator does not work with multicolumns-pks if not has_multiple_pks(model): kwargs['validators'].append(Unique(self.session, model, column)) unique = True # If field is unique, validate it if column.unique and not unique: kwargs['validators'].append(Unique(self.session, model, column)) optional_types = getattr(self.view, 'form_optional_types', (Boolean,)) if ( not column.nullable and not isinstance(column.type, optional_types) and not column.default and not column.server_default ): kwargs['validators'].append(validators.InputRequired()) # Apply label and description if it isn't inline form field if self.view.model == mapper.class_: kwargs['label'] = self._get_label(prop.key, kwargs) kwargs['description'] = self._get_description(prop.key, kwargs) # Figure out default value default = getattr(column, 'default', None) value = None if default is not None: value = getattr(default, 'arg', None) if value is not None: if getattr(default, 'is_callable', False): value = lambda: default.arg(None) else: if not getattr(default, 'is_scalar', True): value = None if value is not None: kwargs['default'] = value # Check nullable if column.nullable: kwargs['validators'].append(validators.Optional()) # Override field type if necessary override = self._get_field_override(prop.key) if override: return override(**kwargs) # Check choices form_choices = getattr(self.view, 'form_choices', None) if mapper.class_ == self.view.model and form_choices: choices = form_choices.get(column.key) if choices: return form.Select2Field( choices=choices, allow_blank=column.nullable, **kwargs ) # Run converter converter = self.get_converter(column) if converter is None: return None return converter(model=model, mapper=mapper, prop=prop, column=column, field_args=kwargs) return None
def get_form(model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, hidden_pk=False, ignore_hidden=True, extra_fields=None): """ Generate form from the model. :param model: Model to generate form from :param converter: Converter class to use :param base_class: Base form class :param only: Include fields :param exclude: Exclude fields :param field_args: Dictionary with additional field arguments :param hidden_pk: Generate hidden field with model primary key or not :param ignore_hidden: If set to True (default), will ignore properties that start with underscore """ # TODO: Support new 0.8 API if not hasattr(model, '_sa_class_manager'): raise TypeError('model must be a sqlalchemy mapped model') mapper = model._sa_class_manager.mapper field_args = field_args or {} properties = ((p.key, p) for p in mapper.iterate_properties) if only: props = dict(properties) def find(name): # If field is in extra_fields, it has higher priority if extra_fields and name in extra_fields: return FieldPlaceholder(extra_fields[name]) # Try to look it up in properties list first p = props.get(name) if p is not None: return p # If it is hybrid property or alias, look it up in a model itself p = getattr(model, name, None) if p is not None and hasattr(p, 'property'): return p.property raise ValueError('Invalid model property name %s.%s' % (model, name)) # Filter properties while maintaining property order in 'only' list properties = ((x, find(x)) for x in only) elif exclude: properties = (x for x in properties if x[0] not in exclude) field_dict = {} for name, p in properties: # Ignore protected properties if ignore_hidden and name.startswith('_'): continue prop = _resolve_prop(p) field = converter.convert(model, mapper, prop, field_args.get(name), hidden_pk) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) return type(model.__name__ + 'Form', (base_class, ), field_dict)
def get_form(model, base_class=form.BaseForm, only=None, exclude=None, field_args=None, extra_fields=None): """ Create a wtforms Form for a given mongoengine Document schema:: from flask_mongoengine.wtf import model_form from myproject.myapp.schemas import Article ArticleForm = model_form(Article) :param model: An RDFAlchemy class :param base_class: Base form class to extend from. Must be a ``wtforms.Form`` subclass. :param only: An optional iterable with the property names that should be included in the form. Only these properties will have fields. :param exclude: An optional iterable with the property names that should be excluded from the form. All other properties will have fields. :param field_args: An optional dictionary of field names mapping to keyword arguments used to construct each field object. :param converter: A converter to generate the fields based on the model properties. If not set, ``ModelConverter`` is used. """ # if not isinstance(model, rdfalchemy.rdfSubject): # raise TypeError('Model must be an RDFAlchemy rdf subject') field_args = field_args or {} # Find properties properties = list(model._sortable_columns.items()) if only: props = dict(properties) def find(name): if extra_fields and name in extra_fields: return FieldPlaceholder(extra_fields[name]) p = props.get(name) if p is not None: return p raise ValueError('Invalid model property name %s.%s' % (model, name)) properties = ((p, find(p)) for p in only) elif exclude: properties = (p for p in properties if p[0] not in exclude) # Create fields field_dict = {"type":TypeField(rel=model.clResource, choice_graph=model.clResource.graph)} for name, p in properties: field = get_field(model, p, name, field_args.get(name)) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) field_dict['model_class'] = model return type(model.__name__ + 'Form', (base_class,), field_dict)
def get_form( model, converter, base_class=form.BaseForm, only=None, exclude=None, field_args=None, hidden_pk=False, ignore_hidden=True, extra_fields=None, ): """ Generate form from the model. :param model: Model to generate form from :param converter: Converter class to use :param base_class: Base form class :param only: Include fields :param exclude: Exclude fields :param field_args: Dictionary with additional field arguments :param hidden_pk: Generate hidden field with model primary key or not :param ignore_hidden: If set to True (default), will ignore properties that start with underscore """ # TODO: Support new 0.8 API if not hasattr(model, "_sa_class_manager"): raise TypeError("model must be a sqlalchemy mapped model") mapper = model._sa_class_manager.mapper field_args = field_args or {} properties = ((p.key, p) for p in mapper.iterate_properties) if only: props = dict(properties) def find(name): # If field is in extra_fields, it has higher priority if extra_fields and name in extra_fields: return FieldPlaceholder(extra_fields[name]) # Try to look it up in properties list first p = props.get(name) if p is not None: return p # If it is hybrid property or alias, look it up in a model itself p = getattr(model, name, None) if p is not None and hasattr(p, "property"): return p.property raise ValueError("Invalid model property name %s.%s" % (model, name)) # Filter properties while maintaining property order in 'only' list properties = ((x, find(x)) for x in only) elif exclude: properties = (x for x in properties if x[0] not in exclude) field_dict = {} for name, p in properties: # Ignore protected properties if ignore_hidden and name.startswith("_"): continue prop = _resolve_prop(p) field = converter.convert(model, mapper, prop, field_args.get(name), hidden_pk) if field is not None: field_dict[name] = field # Contribute extra fields if not only and extra_fields: for name, field in iteritems(extra_fields): field_dict[name] = form.recreate_field(field) return type(model.__name__ + "Form", (base_class,), field_dict)
def convert(self, model, mapper, prop, field_args, hidden_pk): # Properly handle forced fields if isinstance(prop, FieldPlaceholder): return form.recreate_field(prop.field) kwargs = {"validators": [], "filters": []} if field_args: kwargs.update(field_args) if kwargs["validators"]: # Create a copy of the list since we will be modifying it. kwargs["validators"] = list(kwargs["validators"]) # Check if it is relation or property if hasattr(prop, "direction"): # remote_model = prop.mapper.class_ # local_column = prop.local_remote_pairs[0][0] # # kwargs['label'] = self._get_label(prop.key, kwargs) # kwargs['description'] = self._get_description(prop.key, kwargs) # # if local_column.nullable: # kwargs['validators'].append(validators.Optional()) # elif prop.direction.name != 'MANYTOMANY': # kwargs['validators'].append(validators.InputRequired()) # # # Override field type if necessary # override = self._get_field_override(prop.key) # if override: # return override(**kwargs) # # # Contribute model-related parameters # if 'allow_blank' not in kwargs: # kwargs['allow_blank'] = local_column.nullable # if 'query_factory' not in kwargs: # kwargs['query_factory'] = lambda: self.session.query(remote_model) # # if prop.direction.name == 'MANYTOONE': # if self.chosen_enabled: # return QuerySelectField(widget=form.Select2Widget(), # **kwargs) # else: # return QuerySelectField(**kwargs) # # elif prop.direction.name == 'ONETOMANY': # # Skip backrefs # if not local_column.foreign_keys and getattr(self.view, 'column_hide_backrefs', False): # return None # # return QuerySelectMultipleField( # widget=form.Select2Widget(multiple=True), # **kwargs) # elif prop.direction.name == 'MANYTOMANY': # return QuerySelectMultipleField( # widget=form.Select2Widget(multiple=True), # **kwargs) return self._convert_relation(prop, kwargs) elif hasattr(prop, "columns"): # Ignore pk/fk # Check if more than one column mapped to the property if len(prop.columns) > 1: columns = filter_foreign_columns(model.__table__, prop.columns) if len(columns) > 1: warnings.warn("Can not convert multiple-column properties (%s.%s)" % (model, prop.key)) return None column = columns[0] else: # Grab column column = prop.columns[0] form_columns = getattr(self.view, "form_columns", None) or () # Do not display foreign keys - use relations, except when explicitly instructed if column.foreign_keys and prop.key not in form_columns: return None # Only display "real" columns if not isinstance(column, Column): return None unique = False if column.primary_key: if hidden_pk: # If requested to add hidden field, show it return fields.HiddenField() else: # By default, don't show primary keys either # If PK is not explicitly allowed, ignore it if prop.key not in form_columns: return None # Current Unique Validator does not work with multicolumns-pks if not has_multiple_pks(model): kwargs["validators"].append(Unique(self.session, model, column)) unique = True # If field is unique, validate it if column.unique and not unique: kwargs["validators"].append(Unique(self.session, model, column)) optional_types = getattr(self.view, "form_optional_types", (Boolean,)) if ( not column.nullable and not isinstance(column.type, optional_types) and not column.default and not column.server_default ): kwargs["validators"].append(validators.InputRequired()) # Apply label and description if it isn't inline form field if self.view.model == mapper.class_: kwargs["label"] = self._get_label(prop.key, kwargs) kwargs["description"] = self._get_description(prop.key, kwargs) # Figure out default value default = getattr(column, "default", None) value = None if default is not None: value = getattr(default, "arg", None) if value is not None: if getattr(default, "is_callable", False): value = lambda: default.arg(None) else: if not getattr(default, "is_scalar", True): value = None if value is not None: kwargs["default"] = value # Check nullable if column.nullable: kwargs["validators"].append(validators.Optional()) # Override field type if necessary override = self._get_field_override(prop.key) if override: return override(**kwargs) # Check choices form_choices = getattr(self.view, "form_choices", None) if mapper.class_ == self.view.model and form_choices: choices = form_choices.get(column.key) if choices: return form.Select2Field(choices=choices, allow_blank=column.nullable, **kwargs) # Run converter converter = self.get_converter(column) if converter is None: return None return converter(model=model, mapper=mapper, prop=prop, column=column, field_args=kwargs) return None