class QuerySetSelectField(SelectFieldBase): """ Given a QuerySet either at initialization or inside a view, will display a select drop-down field of choices. The `data` property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the queryset will result in a validation error. Specifying `label_attr` in the constructor will use that property of the model instance for display in the list, else the model object's `__str__` or `__unicode__` will be used. If `allow_blank` is set to `True`, then a blank choice will be added to the top of the list. Selecting this choice will result in the `data` property being `None`. The label for the blank choice can be set by specifying the `blank_text` parameter. """ widget = widgets.Select() def __init__(self, label=u'', validators=None, queryset=None, label_attr='', allow_blank=False, blank_text=u'---', **kwargs): super(QuerySetSelectField, self).__init__(label, validators, **kwargs) self.label_attr = label_attr self.allow_blank = allow_blank self.blank_text = blank_text self.queryset = queryset or [] def iter_choices(self): if self.allow_blank: yield (u'__None', self.blank_text, self.data is None) if not self.queryset: return self.queryset.rewind() for obj in self.queryset: label = self.label_attr and getattr(obj, self.label_attr) or obj yield (obj.id, label, obj == self.data) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: if not self.queryset: self.data = None return self.queryset.rewind() for obj in self.queryset: if str(obj.id) == valuelist[0]: self.data = obj break else: self.data = None def pre_validate(self, form): if not self.allow_blank or self.data is not None: if not self.data: raise ValidationError(_(u'Not a valid choice'))
class ReferencePropertyField(fields.SelectFieldBase): """ A field for ``db.ReferenceProperty``. The list items are rendered in a select. :param reference_class: A db.Model class which will be used to generate the default query to make the list of items. If this is not specified, The `query` property must be overridden before validation. :param get_label: If a string, use this attribute on the model class as the label associated with each option. If a one-argument callable, this callable will be passed model instance and expected to return the label text. Otherwise, the model object's `__str__` or `__unicode__` will be used. :param allow_blank: If set to true, a blank choice will be added to the top of the list to allow `None` to be chosen. :param blank_text: Use this to override the default blank option's label. """ widget = widgets.Select() def __init__(self, label=None, validators=None, reference_class=None, get_label=None, allow_blank=False, blank_text='', **kwargs): super(ReferencePropertyField, self).__init__(label, validators, **kwargs) if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, string_types): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label self.allow_blank = allow_blank self.blank_text = blank_text self._set_data(None) if reference_class is not None: self.query = reference_class.all() def _get_data(self): if self._formdata is not None: for obj in self.query: if str(obj.key()) == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): if self.allow_blank: yield ('__None', self.blank_text, self.data is None) for obj in self.query: key = str(obj.key()) label = self.get_label(obj) yield (key, label, (self.data.key() == obj.key()) if self.data else False) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): data = self.data if data is not None: s_key = str(data.key()) for obj in self.query: if s_key == str(obj.key()): break else: raise ValueError(self.gettext('Not a valid choice')) elif not self.allow_blank: raise ValueError(self.gettext('Not a valid choice'))
class QuerySelectField(SelectFieldBase): widget = widgets.Select() def __init__(self, label=None, validators=None, query_factory=None, get_pk=None, get_label=None, allow_blank=False, blank_text='', **kwargs): super(QuerySelectField, self).__init__(label, validators, **kwargs) self.query_factory = query_factory if get_pk is None: self.get_pk = identity_key else: self.get_pk = get_pk if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, (basestring, str, unicode)): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label self.allow_blank = allow_blank self.blank_text = blank_text self.query = None self._object_list = None def _get_data(self): if self._formdata is not None: for pk, obj in self._get_object_list(): if pk == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def _get_object_list(self): if self._object_list is None: query = self.query or self.query_factory() self._object_list = list( (str(self.get_pk(obj)), obj) for obj in query) return self._object_list def iter_choices(self): if self.allow_blank: yield ('__None', self.blank_text, self.data is None) for pk, obj in self._get_object_list(): yield (pk, self.get_label(obj), obj == self.data) def process_formdata(self, valuelist): if valuelist: if self.allow_blank and valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): data = self.data if data is not None: for pk, obj in self._get_object_list(): if data == obj: break else: raise ValidationError(self.gettext('Not a valid choice')) elif self._formdata or not self.allow_blank: raise ValidationError(self.gettext('Not a valid choice'))
class VoteForm(FlaskForm): candidate = SelectField('candidate', choices=[], widget=widgets.Select())
class QuerySetSelectField(fields.SelectFieldBase): """A :class:`~wtforms.fields.SelectField` with the choices populated from the results of a Django :class:`~django.db.models.query.QuerySet`. .. code-block:: python category = QuerySetSelectField(queryset=Category.objects.all()) The values passed in the request are the primary keys, but the ``data`` attribute of the field will be the actual model instance. By default each option displays the result of ``str(instance)``, but this can be customized by passing the ``get_label`` argument. To customize the query based on the request, you can set the ``queryset`` attribute after creating the form instance. For example, to limit the values based on the logged in user: .. code-block:: python class ArticleEdit(Form): title = StringField() series = QuerySetSelectField(allow_blank=True) def edit_article(request, id): article = Article.objects.get(pk=id) form = ArticleEdit(obj=article) form.series.queryset = Series.objects.filter(author=request.user) ... :param queryset: Populate the select with results from this query. :param get_label: The name of a model attribute to use to get the label for each item. Or a callable that takes a model instance and returns a label for it. :param allow_blank: Add a blank choice to the top of the list. Selecting it sets ``data`` to ``None``. :param blank_text: The label for the blank choice. """ widget = widgets.Select() def __init__(self, label=None, validators=None, queryset=None, get_label=None, allow_blank=False, blank_text="", **kwargs): super(QuerySetSelectField, self).__init__(label, validators, **kwargs) self.allow_blank = allow_blank self.blank_text = blank_text self._set_data(None) if queryset is not None: self.queryset = queryset.all() # Make sure the queryset is fresh if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, string_types): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label def _get_data(self): if self._formdata is not None: for obj in self.queryset: if obj.pk == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): if self.allow_blank: yield ("__None", self.blank_text, self.data is None) for obj in self.queryset: yield (obj.pk, self.get_label(obj), obj == self.data) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == "__None": self.data = None else: self._data = None self._formdata = int(valuelist[0]) def pre_validate(self, form): if not self.allow_blank or self.data is not None: for obj in self.queryset: if self.data == obj: break else: raise ValidationError(self.gettext("Not a valid choice"))
class QuerySetSelectField(fields.SelectFieldBase): widget = widgets.Select() def __init__(self, label='', colname=None, id_attr='_id', label_attr='', query={}, validators=None, sort=None, allow_blank=False, blank_text='---', **kwargs): super().__init__(label, validators, **kwargs) self.id_attr = id_attr self.label_attr = label_attr self.allow_blank = allow_blank self.blank_text = blank_text self.colname = colname self.query = query or {} self.sort = sort self.db = get_mongo_db() self.col = self.db[self.colname] self.queryset = self.db[self.colname].find(query) if self.sort and isinstance(self.sort, tuple) and len(self.sort) == 2: self.queryset = self.queryset.sort(*sort) def iter_choices(self): if self.allow_blank: yield ('', self.blank_text, self.data is None) if self.queryset is None: return self.queryset.rewind() for obj in self.queryset: _id = str(obj[self.id_attr]) label = self.label_attr and obj.get(self.label_attr) or _id if isinstance(self.data, list): selected = _id in self.data else: selected = self._is_selected(_id) yield (_id, label, selected) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: if self.queryset is None: self.data = None return query = {} if self.id_attr == "_id": query['_id'] = ObjectId(valuelist[0]) else: query[self.id_attr] = valuelist[0] obj = self.col.find_one(query) if obj: self.data = str(obj.get(self.id_attr)) else: self.data = None def pre_validate(self, form): if not self.allow_blank or self.data is not None: if not self.data: raise ValidationError('Not a valid choice') def _is_selected(self, item): #print("_is_selected : ", item, type(item), self.data, type(self.data)) #BIS <class 'str'> None <class 'NoneType'> return item == self.data
class ReferencePropertyField(f.Field): """ A field for ``db.ReferenceProperty``. The list items are rendered in a select. """ widget = widgets.Select() def __init__(self, label=u'', validators=None, reference_class=None, label_attr=None, allow_blank=False, blank_text=u'', **kwargs): super(ReferencePropertyField, self).__init__(label, validators, **kwargs) self.label_attr = label_attr self.allow_blank = allow_blank self.blank_text = blank_text self._set_data(None) if reference_class is None: raise ValueError('Missing reference_class attribute in ' 'ReferencePropertyField') self.query = reference_class.all() def _get_data(self): if self._formdata is not None: for obj in self.query: key = str(obj.key()) if key == self._formdata: self._set_data(key) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): if self.allow_blank: yield (u'__None', self.blank_text, self.data is None) for obj in self.query: key = str(obj.key()) label = self.label_attr and getattr(obj, self.label_attr) or key yield (key, label, key == self.data) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): if not self.allow_blank or self.data is not None: for obj in self.queryset: if self.data == str(obj.key()): break else: raise ValidationError('Not a valid choice')
class QuerySelectField(SelectFieldBase): """ Based on WTForms QuerySelectField """ widget = widgets.Select() def __init__(self, label=None, validators=None, query_func=None, get_pk_func=None, get_label=None, allow_blank=False, blank_text="", **kwargs): super(QuerySelectField, self).__init__(label, validators, **kwargs) self.query_func = query_func self.get_pk_func = get_pk_func if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, str): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label self.allow_blank = allow_blank self.blank_text = blank_text self._object_list = None def _get_data(self): if self._formdata is not None: for pk, obj in self._get_object_list(): if pk == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def _get_object_list(self): if self._object_list is None: objs = self.query_func() self._object_list = list( (str(self.get_pk_func(obj)), obj) for obj in objs) return self._object_list def iter_choices(self): if self.allow_blank: yield ("__None", self.blank_text, self.data is None) for pk, obj in self._get_object_list(): yield (pk, self.get_label(obj), obj == self.data) def process_formdata(self, valuelist): if valuelist: if self.allow_blank and valuelist[0] == "__None": self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): data = self.data if data is not None: for pk, obj in self._get_object_list(): if data == obj: break else: raise ValidationError(self.gettext("Not a valid choice")) elif self._formdata or not self.allow_blank: raise ValidationError(self.gettext("Not a valid choice"))
class RepeatedPrefetchedKeyPropertyField(SelectMultipleMixin, PrefetchedKeyPropertyField): widget = widgets.Select(multiple=True)
"render_kw": { 'class': 'form-control' } }, "password": { "label": '密码', "widget": widgets.PasswordInput(), "validators": [ validators.DataRequired(message='密码不能为空'), validators.Length(min=6, max=16, message='密码长度必须大于%(min)d且小于%(max)d') ], "render_kw": { 'class': 'form-control' } }, "roles": { "label": '角色', "widget": widgets.Select(), "validators": [ validators.DataRequired(message='角色不能为空'), ], "render_kw": { 'class': 'form-control' } } })
class KeyPropertyField(fields.SelectFieldBase): """ A field for ``ndb.KeyProperty``. The list items are rendered in a select. :param ndb.Model reference_class: A Model class which will be used to generate the default query to make the list of items. If this is not specified, The `query` argument must be provided. :param get_label: If a string, use this attribute on the model class as the label associated with each option. If a one-argument callable, this callable will be passed model instance and expected to return the label text. Otherwise, the model object's `__str__` or `__unicode__` will be used. :param allow_blank: If set to true, a blank choice will be added to the top of the list to allow `None` to be chosen. :param blank_text: Use this to override the default blank option's label. :param ndb.Query query: A query to provide a list of valid options. """ widget = widgets.Select() def __init__(self, label=None, validators=None, reference_class=None, get_label=text_type, allow_blank=False, blank_text='', query=None, **kwargs): super(KeyPropertyField, self).__init__(label, validators, **kwargs) if isinstance(get_label, basestring): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label self.allow_blank = allow_blank self.blank_text = blank_text self._set_data(None) if reference_class is not None: query = query or reference_class.query() if query: self.set_query(query) def set_query(self, query): # Evaluate and set the query value # Setting the query manually will still work, but is not advised # as each iteration though it will cause it to be re-evaluated. self.query = query.fetch() @staticmethod def _key_value(key): """ Get's the form-friendly representation of the ndb.Key. This should return a hashable object (such as a string). """ # n.b. Possible security concern here as urlsafe() exposes # *all* the detail about the instance. But it's also the only # way to reliably record ancestor information, and ID values in # a typesafe manner. # Possible fix: Hash the value of urlsafe return key.urlsafe() def _get_data(self): if self._formdata is not None: for obj in self.query: if self._key_value(obj.key) == self._formdata: self._set_data(obj.key) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): if self.allow_blank: yield ('__None', self.blank_text, self.data is None) for obj in self.query: key = self._key_value(obj.key) label = self.get_label(obj) yield (key, label, (self.data == obj.key) if self.data else False) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): if self.data is not None: for obj in self.query: if self.data == obj.key: break else: raise ValueError(self.gettext('Not a valid choice')) elif not self.allow_blank: raise ValueError(self.gettext('Not a valid choice')) def populate_obj(self, obj, name): setattr(obj, name, self.data)
class RadioSelectField(RadioField): widget = widgets.Select(multiple=False) option_widget = widgets.Select
class QuerySetSelectField(SelectFieldBase): """ Given a QuerySet either at initialization or inside a view, will display a select drop-down field of choices. The `data` property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the queryset will result in a validation error. Specifying `label_attr` in the constructor will use that property of the model instance for display in the list, else the model object's `__str__` or `__unicode__` will be used. If `allow_blank` is set to `True`, then a blank choice will be added to the top of the list. Selecting this choice will result in the `data` property being `None`. The label for the blank choice can be set by specifying the `blank_text` parameter. """ widget = widgets.Select() def __init__( self, label="", validators=None, queryset=None, label_attr="", allow_blank=False, blank_text="---", label_modifier=None, **kwargs, ): super(QuerySetSelectField, self).__init__(label, validators, **kwargs) self.label_attr = label_attr self.allow_blank = allow_blank self.blank_text = blank_text self.label_modifier = label_modifier self.queryset = queryset def iter_choices(self): if self.allow_blank: yield ("__None", self.blank_text, self.data is None) if self.queryset is None: return self.queryset.rewind() for obj in self.queryset: label = (self.label_modifier(obj) if self.label_modifier else (self.label_attr and getattr(obj, self.label_attr) or obj)) if isinstance(self.data, list): selected = obj in self.data else: selected = self._is_selected(obj) yield (obj.id, label, selected) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == "__None": self.data = None else: if self.queryset is None: self.data = None return try: obj = self.queryset.get(pk=valuelist[0]) self.data = obj except DoesNotExist: self.data = None def pre_validate(self, form): if not self.allow_blank or self.data is not None: if not self.data: raise ValidationError(_("Not a valid choice")) def _is_selected(self, item): return item == self.data
class QuerySelectMultipleField(QuerySelectField): """ Very similar to QuerySelectField with the difference that this will display a multiple select. The data property will hold a list with ORM model instances and will be an empty list when no value is selected. If any of the items in the data list or submitted form data cannot be found in the query, this will result in a validation error. """ widget = widgets.Select(multiple=True) def __init__(self, label=None, validators=None, default=None, **kwargs): if default is None: default = [] super(QuerySelectMultipleField, self).__init__(label, validators, default=default, **kwargs) if kwargs.get('allow_blank', False): import warnings warnings.warn( 'allow_blank=True does not do anything for QuerySelectMultipleField.' ) self._invalid_formdata = False def _get_data(self): formdata = self._formdata if formdata is not None: data = [] for pk, obj in self._get_object_list(): if not formdata: break elif pk in formdata: formdata.remove(pk) data.append(obj) if formdata: self._invalid_formdata = True self._set_data(data) return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): for pk, obj in self._get_object_list(): yield (pk, self.get_label(obj), obj in self.data) def process_formdata(self, valuelist): self._formdata = set(valuelist) def pre_validate(self, form): if self._invalid_formdata: raise ValidationError(self.gettext('Not a valid choice')) elif self.data: obj_list = list(x[1] for x in self._get_object_list()) for v in self.data: if v not in obj_list: raise ValidationError(self.gettext('Not a valid choice'))
class QuerySetSelectField(fields.SelectFieldBase): """ Given a QuerySet either at initialization or inside a view, will display a select drop-down field of choices. The `data` property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the queryset will result in a validation error. Specify `get_label` to customize the label associated with each option. If a string, this is the name of an attribute on the model object to use as the label text. If a one-argument callable, this callable will be passed model instance and expected to return the label text. Otherwise, the model object's `__str__` or `__unicode__` will be used. If `allow_blank` is set to `True`, then a blank choice will be added to the top of the list. Selecting this choice will result in the `data` property being `None`. The label for the blank choice can be set by specifying the `blank_text` parameter. """ widget = widgets.Select() def __init__(self, label=None, validators=None, queryset=None, get_label=None, allow_blank=False, blank_text='', **kwargs): super(QuerySetSelectField, self).__init__(label, validators, **kwargs) self.allow_blank = allow_blank self.blank_text = blank_text self._set_data(None) if queryset is not None: self.queryset = queryset.all() # Make sure the queryset is fresh if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, string_types): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label def _get_data(self): if self._formdata is not None: for obj in self.queryset: if obj.pk == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def iter_choices(self): if self.allow_blank: yield ('__None', self.blank_text, self.data is None) for obj in self.queryset: yield (obj.pk, self.get_label(obj), obj == self.data) def process_formdata(self, valuelist): if valuelist: if valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = int(valuelist[0]) def pre_validate(self, form): if not self.allow_blank or self.data is not None: for obj in self.queryset: if self.data == obj: break else: raise ValidationError(self.gettext('Not a valid choice'))
class QuerySelectField(SelectFieldBase): """ Will display a select drop-down field to choose between ORM results in a sqlalchemy `Query`. The `data` property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the query will result in a validation error. This field only works for queries on webapp whose primary key column(s) have a consistent string representation. This means it mostly only works for those composed of string, unicode, and integer types. For the most part, the primary keys will be auto-detected from the model, alternately pass a one-argument callable to `get_pk` which can return a unique comparable key. The `query` property on the field can be set from within a view to assign a query per-instance to the field. If the property is not set, the `query_factory` callable passed to the field constructor will be called to obtain a query. Specify `get_label` to customize the label associated with each option. If a string, this is the name of an attribute on the model object to use as the label text. If a one-argument callable, this callable will be passed model instance and expected to return the label text. Otherwise, the model object's `__str__` or `__unicode__` will be used. If `allow_blank` is set to `True`, then a blank choice will be added to the top of the list. Selecting this choice will result in the `data` property being `None`. The label for this blank choice can be set by specifying the `blank_text` parameter. """ widget = widgets.Select() def __init__(self, label=None, validators=None, query_factory=None, get_pk=None, get_label=None, allow_blank=False, blank_text='', **kwargs): super(QuerySelectField, self).__init__(label, validators, **kwargs) self.query_factory = query_factory if get_pk is None: if not has_identity_key: raise Exception( 'The sqlalchemy identity_key function could not be imported.' ) self.get_pk = get_pk_from_identity else: self.get_pk = get_pk if get_label is None: self.get_label = lambda x: x elif isinstance(get_label, string_types): self.get_label = operator.attrgetter(get_label) else: self.get_label = get_label self.allow_blank = allow_blank self.blank_text = blank_text self.query = None self._object_list = None def _get_data(self): if self._formdata is not None: for pk, obj in self._get_object_list(): if pk == self._formdata: self._set_data(obj) break return self._data def _set_data(self, data): self._data = data self._formdata = None data = property(_get_data, _set_data) def _get_object_list(self): if self._object_list is None: query = self.query or self.query_factory() get_pk = self.get_pk self._object_list = list( (text_type(get_pk(obj)), obj) for obj in query) return self._object_list def iter_choices(self): if self.allow_blank: yield ('__None', self.blank_text, self.data is None) for pk, obj in self._get_object_list(): yield (pk, self.get_label(obj), obj == self.data) def process_formdata(self, valuelist): if valuelist: if self.allow_blank and valuelist[0] == '__None': self.data = None else: self._data = None self._formdata = valuelist[0] def pre_validate(self, form): data = self.data if data is not None: for pk, obj in self._get_object_list(): if data == obj: break else: raise ValidationError(self.gettext('Not a valid choice')) elif self._formdata or not self.allow_blank: raise ValidationError(self.gettext('Not a valid choice'))
from wtforms import widgets, SubmitField from app.models import Profile as ProfileModel Profile_ = model_form( ProfileModel, field_args={ # 'dob': { # 'label': 'Date of Birth' # }, 'age': { 'label': 'Age' }, 'gender': { 'label': 'Gender', 'widget': widgets.Select(), 'default': '' }, 'race': { 'label': 'Race', 'widget': widgets.Select(), 'default': '' }, 'food_allergies': { 'label': 'Food Allergies?', 'widget': widgets.TextInput() }, 'major': { 'label': 'Major', 'widget': widgets.TextInput() },