Example #1
0
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'))
Example #2
0
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'))
Example #3
0
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())
Example #5
0
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"))
Example #6
0
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
Example #7
0
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')
Example #8
0
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"))
Example #9
0
class RepeatedPrefetchedKeyPropertyField(SelectMultipleMixin,
                                         PrefetchedKeyPropertyField):
    widget = widgets.Select(multiple=True)
Example #10
0
            "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'
            }
        }
    })
Example #11
0
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)
Example #12
0
class RadioSelectField(RadioField):
    widget = widgets.Select(multiple=False)
    option_widget = widgets.Select
Example #13
0
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
Example #14
0
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'))
Example #15
0
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'))
Example #16
0
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'))
Example #17
0
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()
        },