Remembering selected dropdown values Python/Flask - html

<option value="1" {{ selected }}>1</option>
<option value="2" {{ selected }}>2</option>
<option value="3" {{ selected }}>3</option>
<option value="4" {{ selected }}>4</option>
I have a flask app with a handful of dropdown menus. I want to pass the selected value when a user submits the form so they see their previous selection on the next page.
Could someone provide a simple example of this? I just cant conceptualize how to accomplish this.
Thanks

Python Flask view
#app.route('/form/')
def form():
# list of tuples representing select options
choices = [(str(x), str(x)) for x in range(1, 20)]
# test if value was passed in (e.g. GET method), default value is 1
selected = request.args.get('choice', '1')
# application 'state' variable with default value and test
state = {'choice': selected}
return render_template('view_form.html', choices=choices, state=state)
Within Jinja template:
{% for row in choices %}
<option value="{{ row[0] }}"{% if row[0] == state.choice %} selected{% endif %}>{{ row[1] }}</option>
{% endfor %}

Related

html form select dynamically preselected value (flask)

I have quite simple application written in flask. On the main page I have a form where you select some settings from few dropdown selects. Sth like this:
<form action="/" method="post">
Choose year:
<div class="form-group">
<select class="form-control" id="year" name="year">
<option value='years' selected>years</option>
<option value='quarters' >quarters</option>
{% for year in years %}
<option value={{year}}>{{year}}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<button class="btn btn-default" type="submit">Show statistics</button>
</div>
</form>
One of values is preselected now. However, when I choose a different setting, click submit and render the page again (according to the new settings), I would like to have as preselected not the value that was preselected at the first but the value I have chosen. What is the proper way to do this?
Use an {% if %} statement to decide which option should be selected.
<select class="form-control" id="year" name="year">
<option value='years' {% if choice == 'years' %} selected {% endif %}>years</option>
<option value='quarters' {% if choice == 'quarters' %} selected {% endif %}>quarters</option>
...
</select>
where choice is a variable you pass to the template that holds the value you chose when you submitted the form.

How to get selected option inside href link in HTML using Django for backend

I have 3 drop down menus. each menu takes it's values through variable passed through object context. here is the view function:
def home_page(request):
template = 'path/to/template.html'
cities = City.objects.all()
all_categories = Category.objects.all()
all_sub_category = Sub_Category.objects.all()
context={
'cities': cities,
'all_categories': all_categories,
'all_sub_category': all_sub_category,
}
return render(request, template, context)
the template is as follow:
{% load staticfiles %}
<select>
{% for city in cities %}
<option value='{{city.city_name}}'>
{{city.city_name}}
</option>
{% endfor %}
</select>
<select>
{% for category in all_categories %}
<option value='{{category.category_name}}'>
{{category.category_name}}
</option>
{% endfor %}
</select>
<select>
{% for sub_category in all_sub_category %}
<option value='{{sub_category.sub_category_name}}' >
{{sub_category.sub_category_name }}
</option>
{% endfor %}
</select>
<span > move to next page </span>
the problem is that the resultant URL is missing all three variables even though all variables are displayed in the drop down menus. here is the resultant link:
http://127.0.0.1:8000/towns///
I tried also the following href:
href="http://domain_name/towns/{{city.city_name.0}}/{{category.category_name.0}}/{{sub_category.sub_category_name.0}}"><span > move to next page </span> </a>
any help or suggestion?
What you have done doesn't work because city variable does not exist outside the for loop.
Similarly for other variables
The best way to do this is wrap all the select tags in a form. Then send the form via GET/POST to a view. Then from that view, you can redirect to the url that you want.
You can also use javascript to redirect to the url directly from the template, but I feel what I mentioned above is much cleaner

show selected option when render posted form in django

I have tried to render a form with a ChoiceField like bellow :
<div class="col-25">
<label for="category">Subcategory</label>
</div>
<div class="col-75">
<select name="category" id="id_category">
{% for x in FilterbyCategory.fields.category.choices %}
<option value="{{ x.0 }}"{% if FilterbyCategory.fields.category.value == x.0 %}selected{% endif %}>
{{ x.1 }}
</option>
{% endfor %}
</select>
</div>
When I submit the form, I don't get the initial option selected.
DO I have a problem here ?
in the view function, I use the request.POST to create an instance :
filterbycategory = FilterbyCategory(request.POST)
I then print the form instance, I get this :
<tr><th><label for="id_category">Category:</label></th><td>
<select name="category" id="id_category">
<option value="">---------</option>
<option value="1" selected>BMW</option>
</select></td></tr>
but the option is not selected in the template rendered manually.
I found the solution. I had to get field value directly and to use safe like bellow :
<option value="{{ x.0 }}"{% if FilterbyCategory.category.value|safe == x.0|safe %} selected{% endif %}> {{ x.1 }} </option>
It works like a charm now.

Django - template form checkbox

I am using Django 1.5. Suppose I have a view located at address: example.com/page/*value* I pass the value to the template in the context.
I want to have a checkbox, that will control the *value*
So for example I go to example.com/page/5
and the checkbox will then look like this:
0
5 (checked)
10
I select 10, click on the button, it redirects me to /page/10
In AngularJS I had ng-model for the value and it wasn't generally a problem, but what's the Django way of doing a similar thing?
Is it even possible by means of Django templates and pure HTML or do I have to write a bit of javascript?
I currently have it as a dropdown:
<ul class="dropdown-menu" aria-labelledby="dropdownMenu3">
<li class="dropdown-header">Chosen: {{value}}</li>
...options...
</ul>
<select> works too, but I cant, quite figure out how to show a value by default:
<select>
<option value="0">0</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
If you are rendering the select box manually, you just need to add the selected attribute
<select>
<option value="0">0</option>
<option value="5" selected>5</option>
<option value="10">10</option>
</select>
In a Django template, if value is in the template context, you can use an if tag to add the attribute.
<select>
<option value="0" {% if value == 0 %}selected{% endif %}>0</option>
<option value="5" {% if value == 5 %}selected{% endif %}>5</option>
<option value="10" {% if value == 10 %}selected{% endif %}>10</option>
</select>
However, manually rendering templates is often a bad idea. You should consider using Django forms where possible, as they help automate validating input and html rendering of form fields.
Redirecting to a new page when an option is selected is a task for JavaScript, not Django.
You can try and use <select> and optionally set selected parameter of <option> with Django {% ifequal a b %} syntax:
<select>
<option {% ifequal value 0 %} selected {% endifequal %}> 0 </option>
<option {% ifequal value 5 %} selected {% endifequal %}> 5 </option>
<option {% ifequal value 10 %} selected {% endifequal %}> 10 </option>
</select>
Similarly you would do checkbox by setting checked parameter
<input type='checkbox' {% ifequal value 0 %}checked{% endifequal %}> 0
....
You can also use form to do the task, simple example:
from django import forms
class SelectionForm(forms.Form):
page = forms.ChoiceField(label="Your label", choices=((0, '0'), (5, '5'), (10, '10)) required=True)
And your view:
from django.views.generic import FormView
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
class SelectionView(FormView):
form_class = SelectionForm
template_name = "your/template.html"
def get_initial(self):
return {'page': self.kwargs['page']}
def form_valid(self, form):
return HttpResponseRedirect(reverse('selection-view', kwargs={'page': form.cleaned_data['page']})
In urls.py you should have numeric param somewhere in your url, called 'page'. Rendering form in template is up to you, also submitting form when select is changed.

Set default value for select html element in Jinja template?

I'm using flask/jinja in order to make a simple web application. I have a table of records which is taken from a db table, and is called by a webpage which loads the list of records. On each row there is a dropdown list (done using the select HTML tag) on a column.
I realize the below code doesn't do what its supposed to, currently the last option (fourth) is automatically selected because of the selected tag. I've left it in to try show what I'm trying to implement.
Ideally I'd want it to check the current record's status (rec.status in the code below) and depending on that, select the appropriate item in the dropdown.
HTML:
<tbody>
{% for rec in records %}
<tr>
<td>{{ rec.task }}</td>
<td>
<select>
<option value ="zero" selected={{rec.status==0}}>Zero</option>
<option value ="first" selected={{rec.status==1}}>First</option>
<option value ="second" selected={{rec.status==2}}>Second</option>
<option value ="third" selected={{rec.status==3}}>Third</option>
</select>
</td>
<td><a href={{ "/update_status/"~rec.id}}>Update</a></td>
</tr>
{% endfor %}
</tbody>
Thanks!
You're on the right track - but currently, you're printing selected in all the options in your select box. You can try something like this to only print selected on the correct option:
<select>
<option value="zero"{% if rec.status==0 %} selected="selected"{% endif %}>Zero</option>
<option value="first"{% if rec.status==1 %} selected="selected"{% endif %}>First</option>
<option value="second"{% if rec.status==2 %} selected="selected"{% endif %}>Second</option>
<option value="third"{% if rec.status==3 %} selected="selected"{% endif %}>Third</option>
</select>
For the future Googlers:
If you're using WTForms and want to set the default selection in Jinja, you might dream that something like this could work:
{{ form.gender(class='form-control', value='male') }}
but it doesn't. Neither does default='male' nor selected='male' (at least not for me in Jinja 2.8 and WTForms 2.1).
If you're desperate and don't want to set it in your forms.py and don't mind getting a little hacky, you can do this:
{{ form.gender(class='form-control hacky', value=data['gender']) }}
<script>
var els = document.getElementsByClassName("hacky");
for (i = 0; i < els.length; i++) {
els[i].value = els[i].getAttribute('value');
}
</script>
This sets it on page load using JavaScript and lets you pass the default selection in the SelectField without having to mess with your forms.py. There's probably a better way of doing this in Jinja, but I haven't found it yet.
Just a small addition to the other answers: you can keep it short by using inline conditions:
<option value="zero" {{'selected' if rec.status==0}}>Zero</option>
And if you are using WTForms like mentioned in another answer, you can set the default value in your route function (but don't forget to process the form as described in the wtforms docs):
form = PreviouslyDefinedFlaskForm()
form.task.default = "third"
form.process()
FYI- for HTML 5, selected="selected" becomes just selected like this:
<option value="zero"{% if rec.status==0 %} selected{% endif %}>Zero</option>
Here's another way of setting the selected value dynamically from a passed variable:
route.py
def route():
roles = ['admin', 'user', 'guest']
user = get_user('John Doe')
return render_template('template.html', user=user, roles=roles)
template.html
<!-- more code -->
<div class="form-group">
<label for="user-role">Role</label>
<select id="user-role" class="custom-select custom-dropdown custom-form-input">
{% for role in roles %}
{% if role == user.role %}
<option value="{{ role.id }}" selected>{{ role }}</option>
{% else %}
<option value="{{ role.id }}">{{ role }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<!-- more code -->