Faculty of Engineering and Mathematical Sciences 
Not logged in (login)

help3403


This forum is provided to promote discussion amongst students enrolled in Agile Web Development (CITS3403).
 
Options:
RSS cloud
Jump to:

Dynamic WTForms and multiple button/submitfields

5 of 419 articles shown, currently no other people reading this forum.
photo
From: Nicholas T.
Date: Sat 16th May, 2:33pm
Actions: 
        Login-to-reply
Hi there,
Just having a lot of issues
As the quiz page has multiple questions only 1 question is served at a time (client-sided 
rendering). To do this in one implementation I used a dynamic form using RadioField:
def StyleOneForm(choices, *args, **kwargs):
	class StaticForm(FlaskForm):
		pass
	StaticForm.radioField = RadioField('radioField', coerce=int, choices=choices)
	StaticForm.submit = SubmitField('Submit')
	return StaticForm()
We want to have multiple implementation of quiz styles so we have complete data abstraction from 
display

Problem is the 2nd implementation uses a list of Button and WTForms doesn't have Button and all 
I see is SubmitField, so I tried this:
def StyleTwoForm(choices, *args, **kwargs):
	class StaticForm(FlaskForm):
		pass
	print("Here8")
	StaticForm.submitFields = [SubmitField(choice) for choice in choices]
	return StaticForm()

Bypassing WTForms I can just do this in template:
{% for choice in question.question_choices %}
                            <button id="btn0" class="btn">{{choice.choice_content}}</button>
                        {% endfor %}

That's a bit crap though, can I do this through WTForms with a list of SubmitField? I tried this 
in template:

{% for submit in form.submitFields %}
                            submit
                        {% endfor %}

But all I'm getting in HTML instead of a submit field I'm getting a
<UnboundField(SubmitField, ((1, 'Taiwanese'),), {})>

Am I missing something?

Dynamic WTForms and multiple button/submitfields

photo
From: Timothy F.
Date: Sat 16th May, 3:54pm
Actions: 
        Login-to-reply
It's a bit hard to see what you are doing. If you are using wtforms and jinja then you are 
definitely doing server side rendering (jinja is interpretted on the server, noit the browser. So 
any button s in a form need to cause an action to happen, but from the wtforms point of view, the 
only available action is to post the form, that's why there is only a submit button available.

If you want to do client side rendering, use AJAX and jquery/DOM is the better solution.

Does that make sense?

Dynamic WTForms and multiple button/submitfields

photo
From: Nicholas T.  O.P.
Date: Sat 16th May, 6:00pm
Actions: 
        Login-to-reply
"Timothy French" <tim.                   wrote:

> It's a bit hard to see what you are doing. If you are using wtforms and jinja then you are 
> definitely doing server side rendering (jinja is interpretted on the server, noit the browser. So 
> any button s in a form need to cause an action to happen, but from the wtforms point of view, the 
> only available action is to post the form, that's why there is only a submit button available.
> 
> If you want to do client side rendering, use AJAX and jquery/DOM is the better solution.
> 
> Does that make sense?
Sorry, server-sided rendering not client-sided

I'll try elaborate a bit

We have a quiz and each quiz has questions

The quiz is served only 1 question at a time

I'm trying to make a generic WTForm that can be passed to the template

Because the content of the WTForm is different every question - such as number of choices or what the choices are - I made a dynamic form

I made a dynamic form by making a function which returns an object of class StaticForm(FlaskForm)

The dynamic form was successfully implemented and is 100% working when I use a RadioField for the question choices:

def StyleOneForm(choices):
	class StaticForm(FlaskForm):
		pass
	StaticForm.radioField = RadioField('radioField', coerce=int, choices=choices)
	StaticForm.submit = SubmitField('Submit')
	return StaticForm()

One first implementation of the quiz utilizes radio buttons, as you can see above (RadioField)
However we also have a second implementation of the quiz so quizzes can be served in multiple styles/ways
Our second implementation of the quiz does not use radio buttons it uses regular buttons
As buttons aren't available in WTForms, I tried an array of submitFields:

def StyleTwoForm(choices):
	class StaticForm(FlaskForm):
		pass
	print("Here8")
	StaticForm.submitFields = [SubmitField(choice) for choice in choices]
	return StaticForm()

I'm having issues with this however, as when the HTML page loads I don't get a SubmitField being rendered, see attached image

Template for StyleOneForm is :
{% for subfield in form.radioField %}
						<tr>
							<td>{{ subfield }}</td>
							<td>{{ subfield.label }}</td>
						</tr>
					{% endfor %}

Template for StyleTwoForm is :
{% for submit in form.submitFields %}
                        {{submit}}
                    {% endfor %}

Thanks

Dynamic WTForms and multiple button/submitfields

photo
From: Timothy F.
Date: Sat 16th May, 10:08pm
Actions: 
        Login-to-reply
I'm not sure what's happening there, but the hack of using a submit field for a button looks a bit dubious.
The 
{{submit}}
will just render 
submit.__repr__()
into the HTML, so maybe use Flask shell to investigate what's happening there.

 From what I can tell, the Unbound form reference comes from the _form attribute not being instantiated. I'm guessing this is because each 
form should only have one submit field? 

Dynamic WTForms and multiple button/submitfields

photo
From: Nicholas T.  O.P.
Date: Sun 17th May, 12:59pm
Actions: 
        Login-to-reply
"Timothy French" <tim.                   wrote:

> I'm not sure what's happening there, but the hack of using a submit field for a button looks a bit dubious.
> The 
> {{submit}}
> will just render 
> submit.__repr__()
> into the HTML, so maybe use Flask shell to investigate what's happening there.
> 
>  From what I can tell, the Unbound form reference comes from the _form attribute not being instantiated. I'm guessing this is because each 
> form should only have one submit field? 

Agreed it looks hacky but as far as I can see there's no other way to do a button using WTForms?
Some people have used multiple submit fields for different functions:
https://stackoverflow.com/questions/35774060/determine-which-wtforms-button-was-pressed-in-a-flask-view
Dynamic forms:
https://stackoverflow.com/questions/51599936/how-do-i-bind-an-flask-wtform-unboundfield

As the dynamic form with RadioField instantiates correctly I assume that the problem is with arrays of fields don't get instantiated correctly 
by WTForms
The following renders perfectly fine:
def StyleTwoForm(choices, *args, **kwargs):
	class StaticForm(FlaskForm):
		pass
	#StaticForm.submitFields = [SubmitField(choice[1]) for choice in choices]
	StaticForm.submitField1 = SubmitField(choices[0])
	StaticForm.submitField2 = SubmitField(choices[1])
	..etc..
	return StaticForm()

There is a FieldList, however this doesn't support SubmitField:
class wtforms.fields.FieldList

I realize that this is becoming a very specific question, I don't have time to focus on this much more as I've already spent too much time on 
this single piece of functionality and will just put something hacky in to make do so I can move on to more important functionality, I've done 
the following:

Form:
def StyleTwoForm(choices, *args, **kwargs):
	class StaticForm(FlaskForm):
		pass
	#StaticForm.submitFields = [SubmitField(choice[1]) for choice in choices]
	StaticForm.len = len(choices)
	if StaticForm.len > 0: StaticForm.submitField1 = SubmitField(choices[0][1])
	if StaticForm.len > 1: StaticForm.submitField2 = SubmitField(choices[1][1])
	... etc
	return StaticForm()

Template:
{% if form.len > 0 %}
                                {{form.submitField0()}}
                            {% endif %}
                            {% if form.len > 1 %}
                                {{form.submitField1()}}
                            {% endif %}
                            {% if form.len > 2 %}
                                {{form.submitField2()}}
                            {% endif %}
                            ... etc


Thanks

This Page


Program written by: [email protected]
Feedback welcome
Last modified:  8:27am May 24 2020