Flask for to have result as variable - python

I have below form which selects the data and redirects to the page user_data
It selects the date and redirects to another page.
Am able to get the data using request.form['Period'] method in python.
But this is not getting called in form action <form action = "/user_data/{{period}}" method="POST"> period variable is empty resulting in Not Found error.
Is there a way to select a value and pass it into a same form
<form action = "/user_data/{{period}}" method="POST">
<label for = "Period" id = "Period">Period</label>
<input list="User_Listing_Period" id ="User_Lst_Period" name = "Period">
<datalist id = "User_data_Period">
{% for row in user_dat_filter %}
<option name = "User_Dat_Period" value = "{{row[0]}}"></option>
{% endfor %}
</datalist>
<div class="submit">
<label for = "Submit" id = "Submit"></label>
<button type="submit">Submit</button>
</div>

two options here:
let form direct to url /user_data, and based on the Period value renders the page i.e it renders the data for that month.
as value is based on user selection, JS can be utilized.
<html>
<body>
<form action = "/user_data/{{period}}" method="POST" id="myForm">
<label for = "Period" id = "Period">Period</label>
<input list="User_Listing_Period" id ="User_Lst_Period" name = "Period">
<datalist id = "User_Listing_Period">
<!-- I commented this, so can check in HTML, you can go with your code
{% for row in user_dat_filter %} -->
<option name = "User_Dat_Period" value = "Aug22"></option>
<option name = "User_Dat_Period" value = "Sep22"></option>
<option name = "User_Dat_Period" value = "Oct222"></option>
<!-- {% endfor %} -->
</datalist>
<div class="submit">
<label for = "Submit" id = "Submit"></label>
<button type="submit">Submit</button>
</div>
</form>
<script>
const myform= document.getElementById("myForm")//identify the form
// add a listener to myform
myform.addEventListener('submit', async (e) => {
e.preventDefault(); //block default submit
const selectedOption=document.getElementById("User_Lst_Period")
let value = selectedOption.value
document.location.href='/user_data/' + value //redirect to value selected by user
})
</script>
</body>
</html>

Related

Django HTML Dropdown

I am trying to make a html dropdown and pass the values into Postgrase SQL database. My dropdown values are being retrieved from another database table. It gives me a MultiValueKeyDictError every time I submit the form. I know I can use forms.py to do the same thing but I want to explore the HTML way of doing this.
My HTML file
<form action = "" method = "post">
{% csrf_token %}
<label for = "LogType"></label>
<input id ="LogType" type = "text" value = "{{ user.department }}">
<label for ="DelayCategory">Delay Category</label>
<select id = "delaycategory" class = "form-control">
{%if user.department == 'TechAssembly'%}
{%for techdelay in techdelay%}
<option value = "{{ techdelay.DelayCode }}">{{ techdelay.DelayCategory}}</option>
{%endfor%}
{%endif%}
{%if user.department == 'Testing'%}
{%for testdelay in testdelay%}
<option value = "{{ testdelay.DelayCode }}">{{ testdelay.DelayCategory}}</option>
{%endfor%}
{%endif%}
</select>
<label for = "iterations">Iterations</label>
<input type = "number" id = "iterations">
<center><input type="submit" value=Submit id = "button"></center>
</form>
My Views.py file
def rulesView(request, user_name):
testdelay = TestingDelayCategory.objects.all()
techdelay = TechDelayCategory.objects.all()
if request.method == "POST":
rulesnew = rules()
rulesnew.DelayCategory = request.GET['DelayCategory']
rulesnew.LogType = request.POST('LogType')
rulesnew.iterations = request.POST('iterations')
rulesnew.save()
context = {
'techdelay':techdelay,
'testdelay':testdelay,
}
return render(request, 'rules/rules.html', context)
rulesnew.DelayCategory = request.GET['DelayCategory']
rulesnew.LogType = request.POST('LogType')
rulesnew.iterations = request.POST('iterations')
Have a second look at this: request.GET should be request.POST and request.POST('LogType') should be request.POST['LogType'] same with iterations.
The error message should include the exact line where the errors was raised. So it would have been way easier to debug if you have told us that the error was raised e.g. in this line rulesnew.LogType = request.POST('LogType')

How to get dynamic html table entries in a form to flask?

I am trying to create a form with an embedded table that the user can dynamically add and remove table rows while entering content into the cell inputs.
HTML
<form id="myForm" action="{{ url_for('hello_world') }}" method="POST">
<div class="form-row text-left">
<div class="col-1 text-left">
<input type="checkbox" id="skills" name="skills" value="Yes">
</div>
<div class = "col-11 text-left">
<h2>TECHNICAL SKILLS</h2>
</div>
</div><!--form-row-->
<div class="form-row">
<table id="myTable" name="skillsTable">
<tr>
<th>Category</th>
<th>Entries</th>
</tr>
</table>
</div><!--form-row-->
<br>
<button type="button" onclick="addSkill()">Add Row</button>
<button type="button" onclick="deleteSkill()">Delete row</button>
<hr>
<input type="submit" value="Submit" onclick="submit()" />
</form>
As you can see in the screenshot [![screenshot of the user form][1]][1] the name attribute is correctly being appended to added cell.
The goal is to have a way to get the table values dynamically created by the user over to the flask template where they can be displayed.
Javascript
<script>
var c1=0;
var c2=0;
function addSkill() {
var table = document.getElementById("myTable");
var row = table.insertRow(-1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = "<input type='text' value=' ' name=cell1_"+c1.toString()+"> ";
cell2.innerHTML = "<input type='text' value=' ' name=cell2_"+c2.toString()+"> ";
c1++;
c2++;
}
function deleteSkill() {
document.getElementById("myTable").deleteRow(-1);
}
</script>
I have tried setting the name attribute for each newly created cell using a counter, but this still does not show up rendered in the flask template:
flask
#app.route('/hello_world', methods=['GET', 'POST'])
def hello_world():
if request.method == 'POST':
result = {}
try:
skills = request.form['skills']
result['skills'] = skills
result['value'] = request.form['cell1_1']
except:
pass
return render_template("result.html",result = result)
result.html
{% if result.skills %}
<p>{{ result.value }}</p>
{% endif %}
In this example, I would expect to see "Language" show up on rendered after submitting the form if the checkbox is selected.
How can I refer to the table in the form from flask and loop through the <input> elements if they are dynamically created? Thx
[1]: https://i.stack.imgur.com/samhG.png
result.html
{% if result.skills %}
{% set skillsTable = result.skillsTable %}
<h2>TECHNICAL SKILLS</h2>
<table>
{% for skill in skillsTable %}
{% if loop.index|int % 2 == 0 %}
<tr><td>{{ skillsTable.pop(0) }}:</td><td>{{ skillsTable.pop(0) }}</td></tr>
{% else %}
<tr><td>{{ skillsTable.pop(0) }}:</td><td>{{ skillsTable.pop(0) }}</td></tr>
{% endif %}
{% endfor %}
{% endif %}
flask
#app.route('/hello_world', methods=['GET', 'POST'])
def hello_world():
if request.method == 'POST':
result = {}
try:
skills = request.form['skills']
result['skills'] = skills
result['skillsTable'] = []
form = request.form
for key, value in form.items():
if key.startswith("cell"):
result['skillsTable'].append(value)
except:
pass
return render_template("result.html",result = result)

Multiple buttons in html, same view, different values

I'm trying to have my html display a session.counter on an HTML page. The counter should increment by a random number, with 4 different options for the range at which it increments (based on buttons). So far, I have all their actions routing to the same view, but I'm not sure how to code the values into the view! Can I nest multiple if-checks into the view? If so, do I need to redirect immediately after each check, or can it be after the if-checks?
EDIT: I've tried adding hidden inputs to make my view more efficient. I'm still a novice, so if the more descriptive your feedback, the easier it will be for me to implement changes and understand why!
Here's the html:
<div id="goldCount">
<h2>Gold Count: {{ session.request.goldCount }}</h2>
</div>
<div id="goldNode">
<h2>Blood Lotus Master</h2>
<h5>(earns 50 to 200 gold coins)</h5>
<form action='/process_gold' method="post">
{% csrf_token %}
<input type="hidden" name="earn" value="reap">
<button type="submit" name="reap">収める - Reap</button>
</form>
</div>
<div id="goldNode">
<h2>Shadow Dance Troupe</h2>
<h5>(earns 35 to 50 gold coins)</h5>
<form action='/process_gold' method = "post">
{% csrf_token %}
<input type="hidden" name="earn" value="weave">
<button type = "submit" name = "weave">織る - Weave</button>
</form>
</div>
<div id="goldNode">
<h2>Necromancy</h2>
<h5>(earns -200 to 200 gold coins)</h5>
<form action='/process_gold' method="post">
{% csrf_token %}
<input type="hidden" name="earn" value="summon">
<button type = "submit" name="summon">召喚 - Summon</button>
</form>
</div>
<div id="goldNode">
<h2>Clan War!</h2>
<h5>(earns -2000 to 2000 gold coins)</h5>
<form action='/process_gold' method="post">
{% csrf_token %}
<input type="hidden" name="earn" value="summon">
<button type="submit" name="war">影の戦争 - Shadow War</button>
</form>
</div>
and here is the views.py file
def index(request):
if 'goldCount' not in request.session:
request.session['goldCount'] = 0
return render(request, 'index.html')
def process_gold(request):
reap = random.randint(50,200)
weave = random.randint(35,50)
summon = random.randint(-200,200)
war = random.randint(-2000,2000)
print(request.POST)
if request.POST['earn'] == 'reap':
request.session['goldCount'] += random.randint(50,200)
if request.POST['earn'] == 'weave':
request.session['goldCount'] += random.randint(35,50)
if request.POST['earn'] == 'summon':
request.session['goldCount'] += random.randint(-200,200)
if request.POST['earn'] == 'war':
request.session['goldCount'] += random.randint(-2000,2000)
return redirect('/')
If you want to send goldCount through to HTML you need to use a render_template rather than a redirect. Store the goldCount into session then just call {{request.session.goldCount}} in your HTML.
Also, the correct if statement would be:
if 'goldCount' not in request.session:
request.session['goldCount'] = 0

Flask-WTForms: dynamically create name and id attributes

My form allows the user to enter a specific number of names for a specific number of basketball teams. These numbers are constantly updated so I need to create a dynamic form.
Let's say I have the following Flask view:
#app.route('/dynamic', methods=['GET', 'POST'])
def dynamic():
teams = ['Warriors', 'Cavs']
name_count = 2
return render_template('dynamic.html', teams=teams, name_count=name_count)
And the following form in the HTML template dynamic.html:
<form method='POST' action='/dynamic'>
{% for team_index in range(teams | count) %}
{% for name_index in range(name_count) %}
<input type="text"
class="form-control"
id="team{{ team_index }}_name{{ name_index }}"
name="team{{ team_index }}_name{{ name_index }}">
{% endfor %}
{% endfor %}
<form>
Which yields the following form:
<form method='POST' action='/dynamic'>
<input type="text" class="form-control" id="team0_name0" name="team0_name0">
<input type="text" class="form-control" id="team0_name1" name="team0_name1">
<input type="text" class="form-control" id="team1_name0" name="team1_name0">
<input type="text" class="form-control" id="team1_name1" name="team1_name1">
<form>
I love the Flask-WTF library so I'm wondering how I can use that (or simply wtforms) to render this form. I'm not sure this is even possible because wtforms requires a hardcoded field name for every input.
Figured this out. I need to use the WTForms Fieldlist and FormField enclosures.
class PlayerForm(FlaskForm):
player = Fieldlist(StringField('Player'))
class TeamForm(FlaskForm):
team = Fieldlist(FormField(PlayerForm))
#app.route('/dynamic', methods=['GET', 'POST'])
def dynamic():
teams = ['Warriors', 'Cavs']
name_count = 2
# Build dictionary to prepopulate form
prepop_data = {'team': [{'player': ['' for p in range(name_count)]} for team in teams]}
# Initialize form
form = TeamForm(data=prepop_data)
return render_template('dynamic.html', form=form)
And unpacking via jinja2 (id and name attributes on first field = team-0-player-0):
<form method="POST" action="/dynamic">
{{ form.csrf_token }}
{% for team in form.team %}
{{ team.csrf_token }}
{% for player in team.player %}
{{ render_field(player) }}
{% endfor %}
{% endfor %}
</form>

Get POST from multiple dropdowns in one form

Have a form where user can change name on attribut Name and change which attribut a is connected to (attribut b).
Template:
"<form id="form1" name="form1" method="post" action="/define_a/{{c.id}}/edit/">
{% csrf_token %}
{% endblock %}
{% block buttons %}
<p><input type="submit" value="Save" /> Cancel
</p>
{% endblock %}
{% block a_rows %}
{% for a, a_form in a_list %}
<tr><td><img class="icon" src="{{images_dir}}/delete-icon.png"
onclick="javascript: return confirmDelete_name('Are you sure?
This will delete the stuff and all associated information.
The removal happens immediately and cannot be undone.', '{{a.id}}', 'delete');" />
</td><td>{{a_form.name}}</td>
<td>
<select name= "test">
<option value = "Null">None</option>
<option value = "{{a_form.id}}" selected>{{a.b}}</option>
{% for a, a_form in a_list %}
<option value = "{{a_form.id}}">{{a.name}}</option>
{% endfor %}"
View:
Checking that it is a post and that it is valid.
post = [myForm(request.POST, instance = test) for a in a's];
for p in post :
if not new_t.b == p:
if p == 'None':
new_t.b = None;
else:
new_t.b = p;
But i can't get all the values from the dropdown in the post.
I get all a.name in but only one value from the dropdown, sometimes I don't get any value at all.
Any ideas?

Categories

Resources