I have a page in my Flask app where the user can query the last 10, 25, 50, or 100 entries of a table. I want the dropdown default selection to display the number of entries that the user has chosen. So if they decided that they want to display 50 entries, the option 50 would be selected in the dropdown menu.
I think I'm close, but my code below isn't doing what I'm aiming for:
app.py:
class log_db(db.Model):
id = db.Column(db.Integer, primary_key=True)
carrier = db.Column(db.String(100), nullable=False)
#app.route('/history', methods=['GET'])
def history():
if not request.args.get('log'):
query_limit = "10"
else:
query_limit = request.args.get('log')
log = log_db.query.order_by(log_db.id.desc()).limit(query_limit).all()
return render_template('history.html', log=log)
history.html:
<form class="form">
<label for="log">Number of change log entries to query:</label>
<select name="log" id="log_query">
<option value="10"
{% if query_limit == 10 %} selected {% endif %}>10</option>
<option value="25"
{% if query_limit == 25 %} selected {% endif %}>25</option>
<option value="50"
{% if query_limit == 50 %} selected {% endif %}>50</option>
<option value="100"
{% if query_limit == 100 %} selected {% endif %}>100</option>
</select><br><br>
<input type="submit" value="Update View" class="create_edit">
</form>
In your render_template return you are not passing the "query_limit". Take care with compare string and integers it could not work.
I edited the code and got it to work. I passed query_limit to history.html and put quotes around each number in the select tag.
app.py
#app.route('/history', methods=['GET'])
def history():
if not request.args.get('log'):
query_limit = "10"
else:
query_limit = request.args.get('log')
log = log_db.query.order_by(log_db.id.desc()).limit(query_limit).all()
return render_template('history.html', log=log, query_limit=query_limit)
history.html
<form class="form">
<label for="log">Number of change log entries to query:</label>
<select name="log" id="log_query">
<option value="10"
{% if query_limit == "10" %} selected {% endif %}>10</option>
<option value="25"
{% if query_limit == "25" %} selected {% endif %}>25</option>
<option value="50"
{% if query_limit == "50" %} selected {% endif %}>50</option>
<option value="100"
{% if query_limit == "100" %} selected {% endif %}>100</option>
</select><br><br>
<input type="submit" value="Update View" class="create_edit">
</form>
Related
i selected a country from a screener function, send this form again to screener function
screenshot
The problem, my form don't keep the last selected country in my form (the variable "country" is send ). I always have the value 'Any' in the form
my list for select
example i
id=1 => 'France'
id=2 => 'Japan'... so if a choose Japan, (id=2) [2]i want to see Japan and not "Any" in the form
[enter image description here]
your help would be appreciated
thank you
screener.html
<form method=POST action="{{ url_for('screener') }}" onchange=submit()>
<table class="table table-sm table-hover">
<thead>
<tr><td>control : {{ country }}</td></tr>
<tr>
<td>Country</td>
<td>
<select id="country" name="country" class="form-select form-select-sm" aria-label="">
<option value="">Any</option>
{% for db_country in db_countries %}
<option value="{{ db_country.id }}" {% if country == db_country.id %} selected {% endif %} >
{{ db_country.id }} - {{ db_country.name }}`</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
</table>
</form>
app.py
`#app.route('/screener/', methods=['POST', 'GET'])
def screener():
db_countries = Country.query.order_by(Country.name.asc()).all()
if request.method == 'POST':
country = request.form['country']
else:
country = 0
return render_template('screener.html', title='Screener',db_countries=db_countries, country=country)`
You are comparing a str to an int. For this reason, the comparison fails.
Change the variable country to an int and it works.
Either you change the type in the endpoint
country = request.form.get('country', 0, type=int)
or in the template.
{% if country | int == db_country.id %} selected {% endif %}
I output datalist, but output pk. I read that it can be removed in data-value like this https://stackoverflow.com/a/48076273/9653855
How can I rewrite the code so that my datalist is displayed in this format <option data-value="1" value="DjangoOneLove"></option>?
my forms
class ListTextWidget(forms.Select):
template_name = 'include/_forms_orders_datalist.html'
def format_value(self, value):
if value == '' or value is None:
return ''
if self.is_localized:
return formats.localize_input(value)
return str(value)
class ChoiceTxtField(forms.ModelChoiceField):
widget=ListTextWidget()
class SimpleOrderAddForm(forms.ModelForm):
#service = forms.ModelChoiceField(queryset=Service.objects.all(), widget=ListTextWidget())
service = ChoiceTxtField(queryset=Service.objects.order_by('-used'))
class Meta:
model = Orders
fields = ['service']
my forms_orders_datalist.html
<input id="ajax_input_{{ widget.name }}" list="{{ widget.name }}" autocomplete="off"
{% if widget.value != None %} name="{{ widget.name }}" value="{{ widget.value|stringformat:'s' }}"{% endif %}
{% include "django/forms/widgets/attrs.html" %}>
<span class="badge rounded-pill bg-warning text-dark" id="ajax-{{ widget.name }}" name="ajax-{{ widget.name }}"></span>
<datalist id="{{ widget.name }}">
{% for group_name, group_choices, group_index in widget.optgroups %}
{% if group_name %}
<optgroup label="{{ group_name }}">{% endif %}{% for option in group_choices %}
{% include option.template_name with widget=option %}{% endfor %}{% if group_name %}
</optgroup>{% endif %}{% endfor %}
</datalist>
My model has this in it:
start_date = models.DateField(default=datetime.date, blank=True)
stop_date = models.DateField(default=datetime.date, blank=True)
In my view I have:
start_date = datetime.date(int(request.POST.get('start_year')),
convert_month_to_int(request.POST.get('start_month')),
int(request.POST.get('start_day')))
end_date = datetime.date(int(request.POST.get('end_year')),
convert_month_to_int(request.POST.get('end_month')),
int(request.POST.get('end_day')))
before I save to the DB.
And the HTML is this:
<label class="col-md-4"> Start Date: </label>
<select class="selectpicker" data-width="auto" name="start_month" id="start_month" required>
{% for month in month_list %}
<option value="{{ month }}" {% if path_start and path_start.1 == month %} selected {% endif %}> {{ month }} </option>
{% endfor %}
</select>
/
<select class="selectpicker" data-width="auto" name="start_day" id="start_day" required>
{% for day in day_list %}
<option value="{{ day }}" {% if path_start and path_start.2 == day %} selected {% endif %}> {{ day }} </option>
{% endfor %}
</select>
/
<select class="selectpicker" data-width="auto" name="start_year" id="start_year" required>
{% for year in year_list %}
<option value="{{ year }}" {% if path_start and path_start.0 == year %} selected {% endif %}> {{ year }} </option>
{% endfor %}
</select>
</div>
<div class="row">
<label class="col-md-4">End Date: </label>
<select class="selectpicker" data-width="auto" name="end_month" id="end_month">
{% for month in month_list %}
<option value="{{ month }}" {% if path_end and path_end.1 == month %} selected {% endif %}> {{ month }} </option>
{% endfor %}
</select>
/
<select class="selectpicker" data-width="auto" name="end_day" id="end_day">
{% for day in day_list %}
<option value="{{ day }}" {% if path_end and path_end.2 == day %} selected {% endif %}> {{ day }} </option>
{% endfor %}
</select>
/
<select class="selectpicker" data-width="auto" name="end_year" id="end_year">
{% for year in year_list %}
<option value="{{ year }}" {% if path_end and path_end.0 == year %} selected {% endif %}> {{ year }} </option>
{% endfor %}
</select>
I get the error 'Required argument 'year' (pos 1) not found' when I try to save. I can't figure out why this is happening. Any advice would be appreciated. Thanks.
I have an html template that includes some Python code and HTML templates. This is a sample below.
Python:
cur1 = g.db.execute('select ID from Students')
students = [dict(ID=row[0]) for row in cur1.fetchall()]
cur2 = g.db.execute('select ID from Quizzes')
quizzes = [dict(ID=row[0]) for row in cur2.fetchall()]
if request.method == 'POST':
if not session.get('logged_in'):
abort(401)
g.db.execute('insert into Results (quiz,student,grade) values '\
'(?,?,?)',[request.form['Quiz'],
request.form['Student'],
request.form['grade']])
g.db.commit()
return render_template('add_result.html',students=students,quizzes=quizzes)
HTML:
<form action="{{ url_for('add_result') }}" method=post>
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student }}">{{ student.ID }}</option>
{% endfor %}
</select>
<input type="number" name="grade">
<input type="submit" value=Submit>
</form>
which outputs the drop down lists in the format I want (integers), however, for example, say the values quiz #1 and student #1 with a grade of 100, they are then input into SQLite as
(2, u"{'ID': 1}", u"{'ID': 1}", 100.0)
How can I get this output?:
(2,1,1,100.0)
You need to convert the values to the right type before sending them to the database. The request.form dict provides a get method that will convert values or raises an error.
g.db.execute(
'insert into Results (quiz,student,grade) values (?,?,?)',
(
request.form.get('Quiz', type=int),
request.form.get('Student', type=int),
request.form.get('grade', type=float)
)
)
It would be much easier (and safer) in the long run to use a form library such as Flask-WTF to parse, convert, and validate the data for you. Also consider using an ORM such as Flask-SQLAlchemy rather than writing raw SQL statements.
The problem was in the HTML:
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student }}">{{ student.ID }}</option>
{% endfor %}
I had "quiz" and "student" as the s, with quiz.ID and student.ID appearing as text in the values. It is the option value that gets returned by the form.
It should be:
<select name="Quiz">
{% for quiz in quizzes %}
<option value="{{ quiz.ID }}">{{ quiz.ID }}</option>
{% endfor %}
</select>
<select name="Student">
{% for student in students %}
<option value="{{ student.ID }}">{{ student.ID }}</option>
{% endfor %}
I can't understand, why this code is not work:
{% set t_c = 'param_1' %}
<div class="col-sm-9">
<select id="category" name="category" class="form-control " required>
<option></option>
{% for c in categories %}
{% if c.id|string == org.category.id %}
{% set t_c = 'param9' %}
<option value="{{ c.id }}" selected>{{ c.name }} </option>
{% else %}
<option value="{{ c.id }}">{{ c.name }} </option>
{% endif %}
{% endfor %}
</select>
</div>
<input id="category_h" name="category_h" type="hidden" value="{{ t_c }}">
Why t_c in last line is 'param_1', when condition {% if c.id|string == org.category.id %} is true?
Thanks.
UPDATE
I have fast solution on JavaScript with jQuery+Select2 like:
var category = $("#category"),
category_h = $("#category_h");
category.select2();
category_h.val(category.find("option:selected").text());
t_c = 'param9' is local to the scope of the for loop
There are workarounds to extend beyond inner block scope