Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Values for SelectWidget/Select2Widget may not be a generator #385

Closed
digitalresistor opened this issue Feb 25, 2019 · 5 comments · Fixed by #469
Closed

Values for SelectWidget/Select2Widget may not be a generator #385

digitalresistor opened this issue Feb 25, 2019 · 5 comments · Fixed by #469

Comments

@digitalresistor
Copy link
Member

If you create a widget with a keyword argument that is a generator for values and you validate the form and render the form you will lose all your values in the rendered output as the generator won't be generating anymore.

This bit me pretty hard tonight and took me a while to debug, even though I would consider a generator a "a sequence" if one were to look at the documentation.

Maybe it should internally create a list if the incoming type is not a list? Or some other way save the result from _validate_choices so that it is computed once instead of each time.

@stevepiercy stevepiercy changed the title Values for SelectWidget/Select2Widget may not be an generator Values for SelectWidget/Select2Widget may not be a generator Aug 26, 2020
@stevepiercy
Copy link
Member

@bertjwregeer can you provide a code sample that reproduces this issue? I tried with this example modified from deformdemo, but I think I missed something.

    @view_config(renderer="templates/form.pt", name="select_with_multiple")
    @demonstrate("Select Widget (with multiple)")
    def select_with_multiple(self):

        def choices_generator():
            for value in range(3):
                yield(value, value)

        choices = choices_generator()

        class Schema(colander.Schema):
            pepper = colander.SchemaNode(
                colander.Set(),
                widget=deform.widget.SelectWidget(
                    values=choices, multiple=True
                ),
            )

        schema = Schema()
        form = deform.Form(schema, buttons=("submit",))

        return self.render_form(form)

@digitalresistor
Copy link
Member Author

You need to submit the form at least once (and validate, but have it fail validation on another form input for instance). At that point when you render the form again the generator will no longer return any values, and all choices will be blank.

@digitalresistor
Copy link
Member Author

Also, I think I meant _normalize_choices not _validate_choices.

@stevepiercy
Copy link
Member

I modified the mini.py example.

class ExampleSchema(deform.schema.CSRFSchema):
    def choices_generator():
        for value in range(3):
            yield(value, value)

    choices = choices_generator()

    pepper = colander.SchemaNode(
        colander.Set(),
        widget=deform.widget.SelectWidget(
            values=choices, multiple=True,
        ),
    )

    name = colander.SchemaNode(colander.String(), title="Name")

Submit that without entering a value for name, and the set of pepper values does not appear. Nasty, evil, formses. I think I got a fix for this.

@stevepiercy
Copy link
Member

@bertjwregeer I opened a PR for you to try out and review. #469

I couldn't figure out how Deform could save the generated values into a list so it doesn't have to regenerate them on each load/submission.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants