Sqlite insert in Flask - python

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 %}

Related

Flask how to set HTML dropdown selected value based on current choice

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>

reading column names from joined query in flask-sqlalchemy

so i've got this long query here:
showings = db.execute("SELECT showings.cinema_id, showings.movie_id,\
cinemas.name, movies.name FROM showings JOIN\
cinemas ON showings.cinema_id=cinemas.id JOIN\
movies ON showings.movie_id=movies.id WHERE\
showings.id = :id",
{"id": cinema_id}).fetchall()
return render_template("showings.html", showings2=showings2)
and then in the template:
{% for showing in showings2 %}
<option value="{{ showing.id }}">
{{ showing.name }} #{{ showing.name }}
</option>
{% endfor %}
Issue being that due to same column names in two different tables, current template gives back same content twice, that is the value of cinema.name
Any option to bypass it ?
Rename the columns using aliases:
showings = db.execute(
"""SELECT showings.cinema_id
, showings.movie_id
, cinemas.name AS cinema_name
, movies.name AS movie_name
FROM showings
JOIN cinemas ON showings.cinema_id=cinemas.id
JOIN movies ON showings.movie_id=movies.id
WHERE showings.id = :id""", {"id": cinema_id}).fetchall()
and use said aliases in the template:
<option value="{{ showing.id }}">
{{ showing.cinema_name }} # {{ showing.movie_name }}
</option>

I wanna add number which is correspond to the number of this list's content

Now index.html is
<html>
 <head>
 <script type="text/javascript" src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.8.2/chosen.jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.jquery.js"></script>
 <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/chosen/1.4.2/chosen.css">
 </head>
 <body>
<select id="mainDD" data-placeholder="Choose" class="chzn-select" style="width:600px;">
{% for i in json_data.items.values %}
<option>{{ i }}</option>
{% endfor %}
</select>
<select name="type" id="type1">
{% for j in json_data.type1.values %}
<option>{{ j }}</option>
{% endfor %}
</select>
<select name="type" id="type2">
{% for k in json_data.type2.values %}
<option>{{ k }}</option>
{% endfor %}
</select>
<select name="type" id="type3">
{% for l in json_data.type3.values %}
<option>{{ l }}</option>
{% endfor %}
</select>
<select name="type" id="type4">
{% for m in json_data.type4.values %}
<option>{{ m }}</option>
{% endfor %}
</select>
<script type="text/javascript">
$(document).ready(function () {
$('#mainDD').on('change', function() {
console.log($(this).val());
console.log($('#mainDD :selected').text()) ;
var thisType = "type" + $(this).val();
for(i=1; i<5; i++) {
var thisId = "type" + i;
console.log(thisType + " " + thisId);
if(thisType !== thisId) {
$("#"+thisId).hide();
}
else {
$("#"+thisId).show();
}
}
}).trigger('change');
});
</script>
</body>
</html>
I wanna add number to tag like .So my ideal output is
<select name="type" id="type1">
<option value="1">a-1</option>
<option value="2">a-2</option>
<option value="3">a-3</option>
<option value="4">a-4</option>
</select>
<select name="type" id="type2">
<option value="5">b-1</option>
<option value="6">b-2</option>
<option value="7">b-3</option>
<option value="8">b-4</option>
<option value="9">b-5</option>
</select>
<select name="type" id="type3">
<option value="10">c-1</option>
<option value="11">c-2</option>
</select>
<select name="type" id="type4">
<option value="12">d-1</option>
<option value="13">d-2</option>
<option value="14">d-3</option>
</select>
But now j&k&l&m is read by json file and this jon file maybe is varied the number of contents.For example, now j has
{'type1': [{'---': '---', ‘A’: ‘a’, ‘B’: ‘b’, ‘C: ‘c’, ‘D’: ‘d’}]} but maybe in the future j has {'type1': [{'---': '---', ‘A’: ‘a’, ‘B’: ‘b’}]} or {'type1': [{'---': '---', ‘A’: ‘a’, ‘B’: ‘b’, ‘C: ‘c’, ‘D’: ‘d’,'E':'e','F','f'}]} so I wanna show these value by using the number of value, but I cannot understand how I can do it.How should I write it?
views.py is
from collections import OrderedDict
from django.shortcuts import render
import json
def index(request):
with open('./data/data.json', 'r') as f:
json_data = json.loads(f.read(), object_pairs_hook=OrderedDict)
return render(request, 'index.html', {'json_data': json_data})
By seeing an answer,I wrote in index.html
{% preprocessed = [] %}
{% counter = 0 %}
{% for key in ["type1", "type2", "type3", "type4"]: %}
{% values = [(i + counter, value) for i, value in enumerate(json_data[key].values())] %}
{% preprocessed.append((key, values)) %}
{% counter = len(data[key]) %}
{% for key, values in preprocessed %}
<select name="type" id="{{ key }}">
{% for counter, value in values %}
<option value="{{ counter }}">{{ value }}-{{counter}}</option>
{% endfor %}
</select>
{% endfor %}
TemplateSyntaxError at /app/
Invalid block tag on line 14: 'preprocessed'. Did you forget to register or load this tag? error happens.
Not sure why you need a sequential numbering given that you could probably do something clever with jQuery, but if you want the output like you've shown, you can pre-process your json_data (in views.py):
from collections import OrderedDict
from django.shortcuts import render
import json
def index(request):
with open('./data/data.json', 'r') as f:
json_data = json.loads(f.read(), object_pairs_hook=OrderedDict)
preprocessed = []
counter = 0
for key in ["type1", "type2", "type3", "type4"]:
values = [(i + counter, value) for i, value in enumerate(json_data[key].values())]
preprocessed.append((key, values))
counter = len(data[key])
return render(request, 'index.html', {'preprocessed': preprocessed})
And then pass this in your context (to index.html):
{% for key, values in preprocessed %}
<select name="type" id="{{ key }}">
{% for counter, value in values %}
<option value="{{ counter }}">{{ value }}-{{counter}}</option>
{% endfor %}
</select>
{% endfor %}

Django - Getting 'Required argument 'year' (pos 1) not found' error when trying to use datetime

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.

How to set/get variable in Jinja2

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

Categories