Git Product home page Git Product logo

Comments (8)

HK-Mattew avatar HK-Mattew commented on May 25, 2024 1

@Daverball I can't send the raw data. Because I use the API to submit form data from my website and also to use the API externally (outside the browser).

from wtforms.

azmeuk avatar azmeuk commented on May 25, 2024

Hi. Can you describe your usecase?
Currently choices is not expected to be a dynamical list, but it can be a method that would be called when the Form object is created. Maybe you can do what you want with select = wtforms.SelectField(choices=lambda: ["foo", "bar"])?

from wtforms.

HK-Mattew avatar HK-Mattew commented on May 25, 2024

Hello,

See my code example:

from wtforms import Form, SelectField, validators



class MyForm(Form):
    def render_visitor_timer_choices():


        choices = [
            (1, 'One'),
            (2, 'Two'),
            (3, 'Three'),
            (4, 'Four')
        ]

        return choices

    visitor_timer = SelectField(
        label='Time in seconds',
        validators=[
            validators.Optional(),
            validators.NumberRange(
                min=1,
                max=4
            )
        ],
        choices=render_visitor_timer_choices,
        coerce=int,
        validate_choice=True,
        render_kw={
            'data-required': 'true'
        }
    )



form = MyForm(data={'visitor_timer': 5})

print(form.visitor_timer.choices) # Result: [(1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four')]

print(form.validate()) # Result: True

print(form.visitor_timer.data) # Result: 5

"""
The response from *form.validate()* is True for the value 5 which is not in the SelectField's choices.

Shouldn't *form.validate()* be False?
"""

from wtforms.

azmeuk avatar azmeuk commented on May 25, 2024

Sharing my investigation: the minimal form I could write to reproduce this is:

>>> from wtforms import Form, SelectField, validators
... from werkzeug.datastructures import ImmutableMultiDictMixin
...
... class MyForm(Form):
...     visitor_timer = SelectField(
...         validators=[validators.Optional()],
...         choices=[('1', 'One')],
...     )
...
... form = MyForm(data={'visitor_timer': '5'})
... print(form.validate())
True

The validation result is False as expected if the Optional validator is removed:

>>> from wtforms import Form, SelectField, validators
...
... class MyForm(Form):
...     visitor_timer = SelectField(
...         choices=[('1', 'One')],
...     )
...
... form = MyForm(data={'visitor_timer': '5'})
... print(form.validate())
False

Or if Optional is kept but the form is filled with formdata instead of data:

>>> from wtforms import Form, SelectField, validators
... from werkzeug.datastructures import ImmutableMultiDict
...
... class MyForm(Form):
...     visitor_timer = SelectField(
...         validators=[validators.Optional()],
...         choices=[('1', 'One')],
...     )
...
... form = MyForm(ImmutableMultiDict({'visitor_timer': '5'}))
... print(form.validate())
False

I think what is going on is: when the form is initialized with data instead of formdata, Optional looks for data in formdata, considers there is no data there, so it interrupts the validation chain:

def __call__(self, form, field):
if (
not field.raw_data
or isinstance(field.raw_data[0], str)
and not self.string_check(field.raw_data[0])
):
field.errors[:] = []
raise StopValidation()

What is your real-world usecase? Do you really use form validation without passing form data, or was it just there to fill the bug report?

from wtforms.

HK-Mattew avatar HK-Mattew commented on May 25, 2024

Hello,

I use data= instead of formdata= because I'm using wtforms to validate data received through my api created with Flask-Restfull.

Then I receive the request data through:

data = request.get_json()
form = MyForm(data=data)

And I do validation and so on...

Based on your answer, my question now is:
If I use

form = MyForm(ImmutableMultiDict(data))

will this work correctly?

from wtforms.

Daverball avatar Daverball commented on May 25, 2024

@HK-Mattew For your example form this will work but it will not work for all the possible field types since formdata is inherently flat and consists of plain strings and uploaded files, while object data can be of an arbitrary type and can also be nested through use of things like FieldList and FormField. How the corresponding formdata should look like compared to the object data will depend on the specific field, but it's not a trivial conversion.

But I also don't really understand your use-case, how are you generating the JSON payload? Or is your goal to provide both a generic API interface and a renderable form from a single form definition and get shared validation regardless of input method? Something like pydantic should be better suited towards generic input validation. Generating a wtforms.Form class from a pydantic.Model should be a much easier thing to implement.

from wtforms.

HK-Mattew avatar HK-Mattew commented on May 25, 2024

Hi @Daverball ,

I'm generating the raunchy JSON payload from javascript. In this case I create the object. I already use Pydantic models, but I didn't think about putting them in the foreground to validate the data. But it's a good option you gave me.

from wtforms.

Daverball avatar Daverball commented on May 25, 2024

@HK-Mattew In that case couldn't you just submit the raw formdata, rather than try to create a JSON payload? It seems like a lot of work to juggle around the backend data representation in the frontend if ultimately you just want to validate the form input.

from wtforms.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.