How to make Flask-WTFoms update labels dynamically from list of label names?

前端 未结 2 971
萌比男神i
萌比男神i 2021-01-21 08:55

I use WTForms to define form for data filtering it is defined like this (My goal is to have user specified labels for BooleanFields set, I let each user to name labels for field

相关标签:
2条回答
  • 2021-01-21 09:00

    The approach that you have taken, calendar_colors_descriptions is assigned in the body of your form class.

    This means that it is only evaluated once - when the forms module is first imported - and so the field label values are fixed until the server is restarted. In effect, the label values are part of the class definition, and so common across all instances of the class.

    This example code is similar to yours;

    import random
    import wtforms
    
    
    def get_labels(labels=None):
            if labels is None:
                labels = ['red', 'amber', 'green']
            # Simulate data changes by shuffling the list.
            random.shuffle(labels)
            return labels
    
    
    class StaticLabelForm(wtforms.Form):
    
        # labels is set when the class is compiled at import time.
        labels = get_labels()
    
        foo = wtforms.BooleanField(labels[0], default=True)
        bar = wtforms.BooleanField(labels[1], default=True)
        baz = wtforms.BooleanField(labels[2], default=True)
    

    Each time we instantiate a new StaticLabelForm, the labels are always the same, because the get_labels function is only called once.

    >>> static1 = StaticLabelForm()
    >>> for field in static1: print(field.label, field)
    ... 
    <label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
    <label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
    <label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">
    
    >>> static2 = StaticLabelForm()
    >>> for field in static2: print(field.label, field)
    ... 
    <label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
    <label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
    <label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">
    

    We can fix this by passing the label values to the form's __init__ method, and setting them on the fields inside the __init__ method.

    class DynamicLabelForm(wtforms.Form):
    
        # Don't set the labels here
        foo = wtforms.BooleanField(default=True)
        bar = wtforms.BooleanField(default=True)
        baz = wtforms.BooleanField(default=True)
    
        def __init__(self, labels=None, **kwargs):
            super().__init__(**kwargs)
            # super(DynamicLabelForm, self).__init__(**kwargs) for python2!
            if labels is None:
                labels = ['red', 'amber', 'green']
            self['foo'].label = wtforms.Label(self['foo'].id, labels[0])
            self['bar'].label = wtforms.Label(self['bar'].id, labels[1])
            self['baz'].label = wtforms.Label(self['baz'].id, labels[2])
    

    Now the labels are reset on each new form:

    >>> dynamic1 = DynamicLabelForm(labels=get_labels())
    >>> for field in dynamic1: print(field.label, field)
    ... 
    <label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
    <label for="bar">red</label> <input checked id="bar" name="bar" type="checkbox" value="y">
    <label for="baz">green</label> <input checked id="baz" name="baz" type="checkbox" value="y">
    
    >>> dynamic2 = DynamicLabelForm(labels=get_labels())
    >>> for field in dynamic2: print(field.label, field)
    ... 
    <label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
    <label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
    <label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">
    
    0 讨论(0)
  • 2021-01-21 09:11

    Create a sample form as follows:

    from flask_wtf import FlaskForm
    from wtforms import StringField
    from wtforms.validators import DataRequired, Length
    from wtforms.fields import Label  #<==This is the key
    
    #in forms.py
    class MyForm(FlaskForm):
        name = StringField('Your Name', validators=[DataRequired(), Length(min=2, max=20)])
        submit = SubmitField('Sign Up')
    
    #in route.py
    from forms import MyForm
    #initialize your app
    
    @app.route("/some-test-route", methods = ["GET","POST"])
    def someTestRoute():
        form = MyForm
        if some condition:
            #change the label as follows.
            form.name.label = Label(field_id = "name", text = "Your New Field Description Goes Here.")
            #The above line creates the following lable object
            #<label for="name">Your New Field Description Goes Here.</label>
            #which replaces the current label object that is
            #<label for="name">yourname</label>
        if form.validate_on_submit():
            #do something
            return redirect(url_for(endpoint = "someEndPoint"))
        return render_template("WhereEverYour_MyForm_Template.html")
    
    0 讨论(0)
提交回复
热议问题