Why isn't my second Jinja for loop running? - python

Im trying to fetch users from my sql database with sqlite 3 and displaying the names in a form to pick 2 and set up a match. But when i pass the variables through only my first jinja for loop runs and it leaves the second multiple selection box empty.
I've tried it with passing the same variable for both loops and different variables one for each, and the second one still doesn't populate.
from flask import Flask
from flask import render_template
import sqlite3
con = con = sqlite3.connect('chess-test.db')
cur = con.cursor()
app = Flask(__name__)
#app.route('/')
def index():
users = cur.execute('''SELECT * FROM chess ORDER BY hcp ''')
return render_template("index.html", users=users)
#app.route('/game')
def game():
names = cur.execute('''SELECT * FROM chess ORDER BY name ''')
users = cur.execute('''SELECT * FROM chess ORDER BY name ''')
return render_template("game.html", names1=names, users=users)
and my jinja template looks like this.
<body>
<div class="container">
<div class="text-center">
<div class="display-4">Hvem skal spille?</div>
</div>
<div class="form-group">
<select multiple class="form-control">
{% for item in names1 %}
<option>{{ item[0] }}</option>
{% endfor %}
</select>
<label for="exampleFormControlSelect2">mod</label>
<select multiple class="form-control">
{% for item in users %}
<option>{{ item[0] }}</option>
{% endfor %}
</select>
</div>
</div>
and here is the resulting page.

Read the queryset before executing next query. Refer here
#app.route('/game')
def game():
cur.execute('''SELECT * FROM chess ORDER BY name ''')
names = cur.fetchall()
cur.execute('''SELECT * FROM chess ORDER BY name ''')
users = cur.fetchall()
return render_template("game.html", names1=names, users=users)

Related

CS50 Finance writing to database issue

I am having another issue with CS50 finance and would really appreciate some help.
So I am working on the BUY section, and I have implemented an extra step, where you type in what stock you want, and how much of it you want, then it takes you to a new html page to confirm that you want to buy the stock. This pages tells you how many shares you will buy, how much it costs, and what your cash balance will be after you buy the shares.
My issue is that when I go to actually buy the stock on the confirmation page, I get errors that say my variables (specifically balance, shares and price_per_share) are undefined and I cannot figure out why. I will attached the relevant portions of my code below. Thanks again.
Application.PY:
#app.route("/buy", methods=["GET", "POST"])
#login_required
def buy():
if request.method == "POST":
quote = lookup(request.form.get("symbol"))
if quote == None:
return apology("invalid symbol", 400)
try:
shares = int(request.form.get("shares"))
except:
return apology("shares must be a positive integer", 400)
if shares <= 0:
return apology("can't buy less than or 0 shares", 400)
users= db.execute("SELECT cash FROM users WHERE id= :user_id", user_id=session["user_id"])
cash_remaining = users[0]["cash"]
price_per_share = quote["price"]
total_price = price_per_share * shares
balance = cash_remaining-total_price
symbol=quote["symbol"]
return render_template ("confirmation.html", cash_remaining=cash_remaining, price_per_share=price_per_share, total_price=total_price,shares=shares, symbol=symbol, balance=balance)
else:
return render_template ("buy.html")
#app.route("/confirmation", methods=["GET", "POST"])
#login_required
def confirmation():
if request.method == "POST":
db.execute("UPDATE users SET cash = cash = :balance WHERE id = :user_id", balance=balance, user_id=session["user_id"])
db.execute("INSERT INTO transactions (user_id, symbol, shares, price_per_share) VALUES(:user_id, :symbol, :shares, :price_per_share)",
user_id=session["user_id"],
symbol=request.form.get("symbol"),
shares=shares,
price_per_share=price_per_share)
flash ("Bought!")
return render_template("index.html")
else:
return render_template("confirmation.html")
here is my buy.html code in case needed:
{% extends "layout.html" %}
{% block title %}
Quote
{% endblock %}
{% block main %}
<form action="/buy" method="post">
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="symbol" placeholder="Symbol" type="text" required/>
</div>
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="shares" placeholder="Shares Wanted" type="number" min="1" required />
</div>
<button class="btn btn-primary" type="submit">Get Price</button>
</form>
{% endblock %}
and finally my confirmation.html:
{% extends "layout.html" %}
{% block title %}
Quote
{% endblock %}
{% block main %}
<form action="/confirmation" method="post">
<p>Stock Symbol ={{symbol}}</p>
<p>Shares to be purchased = {{shares}}</p>
<p>Total Transaction Cost {{total_price | usd}}</p>
<p>Current Cash = {{cash_remaining | usd}}</p>
<p>Balance after transaction = {{balance |usd}}</p>
<button class="btn btn-primary" type="submit">Buy</button>
</form>
{% endblock %}
There are no values submitted with the form in confirmation.html. Some options:
add the data to the session array
create hidden input controls to carry the data back to the server
give the button element a name, and a json encoded string of the values that confirmation will need as its value.
The confirmation route doesn't (try to) get any values from the form (eg request.form.get).

Update sql database using variables from Python Flask HTML list

I am trying to create a Website form (using Python Flask and WTForms and pyodbc for my database connection). I have a sql server database that is displaying the records to update in the html.
My goal is to update the "Unit price" and "discount" for each record in the database. The form I created requires an input in each of these fields from the user. Because that database data is displayed in a list, I'm not sure how to match up the data back to the database.
When I submit the form as is, only the first record is inserted into the database and This is what the form looks in my testing environment (please forgive the horrible formatting). The first column is for the "unit price" and the second is for the "discount" the only record inserted into the database is the first one and the element and element name are not mapped properly.
Is there a way to reference the columns in "elementdata"? (ex: elementdata.UniqueKey)
How can I create the connection between the data displayed in the html to the data inserted to the database?
EDIT: I watched a few of Corey Schafer's video's on youtube and found them helpful but they haven't quite solved my problem.(https://www.youtube.com/channel/UCCezIgC97PvUuR4_gbFUs5g)
I'm currently heading into the direction of creating my own list and then calling that list in the HTML. So instead of
elementdata = cur.execute("SELECT UniqueKey, Element, ElementName, Quantity FROM FakePricingData WHERE ClientName=clientname").fetchall()
I tried:
uniquekey = cur.execute("SELECT UniqueKey FROM FakePricingData WHERE ClientName=clientname").fetchall()
element = cur.execute("SELECT Element FROM FakePricingData WHERE ClientName=clientname").fetchall()
elementname = cur.execute("SELECT ElementName FROM FakePricingData WHERE ClientName=clientname").fetchall()
elementdata = [uniquekey, element, elementname]
However, when referencing elementdata[0], insead of getting just the uniquekey, I get the entire first row.
How can I get what I'm looking for? I would appreciate any help I can get!
#app.route("/VendorPricing/Example", methods=['GET', 'POST'])
#login_required
def vendorpricing():
clientname = "Example Credit Union"
elementdata = cur.execute("SELECT UniqueKey, Element, ElementName, Quantity FROM FakePricingData WHERE ClientName=clientname").fetchall()
form = VendorPricingForm()
if form.validate_on_submit():
for elementdata in elementdata:
loggedinuserid = current_user.get_id()
query = "INSERT INTO FakeQuoteData (UniqueKey, Element, ElementName, Quantity, UnitPrice, Discount, ClientName, SubmittedBy, LoggedInUserId) VALUES (?,?,?,?,?,?,?,?,?);"
query_values = [form.uniquekey.data, form.element.Element, 'NULL', '0', form.unitprice.data, form.discount.data, clientname, form.submittedby.data, loggedinuserid]
cur.execute(query, query_values)
cur.commit()
flash('Your pricing has been submitted!', 'success')
return redirect(url_for('welcome'))
return render_template('vendorpricing.html', form=form, clientname=clientname, elementdata=elementdata)
------ form ------
class VendorPricingForm(FlaskForm):
unitprice = IntegerField('Unit Price', validators=[DataRequired()])
discount = IntegerField('Discount')
uniquekey = StringField('Unique Key')
submittedby = StringField('Submitted By', validators=[DataRequired()])
submit = SubmitField('Submit')
{% extends "layout.html" %}
{% block content %}
<h2>{{ title }}</h2>
<body>
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="vendor-form-group">
{{ form.unitprice.label(class="form-control-label") }}
{{ form.discount.label(class="form-control-label") }}
{% for elementdata in elementdata %}
<p>
{{ elementdata }}
{{ form.unitprice }}
{{ form.discount }}
</p>
{% endfor %}
{{ form.submittedby.label(class="form-control-label") }}
<p>{{ form.submittedby }}</p>
{{ form.submit }}
</div>
</form>
</body>
{% endblock content %}
You can try InputRequired() instead of DataRequired()

Unable to update record with Flask, MySQL

I'm working on a music database app with Flask, and I have a page where I can insert a record into the database that works how it should. Yesterday, I built a page where you can edit the values of the record. For the route, I copied the code from another, more simple app I made and re-wrote it for this app. When I visit the edit page, it fills the text boxes with the current values for the record...but when I change any of the items and submit it, nothing happens. It renders the page that I specified in the route after submit, but when I query the table nothing has changed.
Here's the route:
#app.route('/edit_album/<string:catno>/', methods=['GET', 'POST'])
def edit_album(catno):
cur = mysql.connection.cursor()
# Get article by catno
result = cur.execute("SELECT * FROM albums WHERE catno = %s", [catno])
album = cur.fetchone()
form = AlbumForm()
form.artist.data = album['artist']
form.title.data = album['title']
form.year.data = album['year']
form.rlabel.data = album['label']
form.genre.data = album['genre']
if request.method == 'POST':
# album art
#cover =
catno = album['catno']
artist = form.artist.data
title = form.title.data
year = form.year.data
rlabel = form.rlabel.data
genre = form.genre.data
# format (lp or tape)
# Create Cursor
cur = mysql.connection.cursor()
# Execute cursor
cur.execute("UPDATE albums SET artist=%s, title=%s, year=%s, label=%s, genre=%s WHERE catno=%s", (artist, title, year, rlabel, genre, catno))
# Commit to DB
mysql.connection.commit()
# Close DB connection
cur.close()
return redirect(url_for('view_album', catno=catno))
return render_template('edit_album.html', album=album, form=form)
And here's the actual edit page:
{% extends 'layout.html' %}
{% block body %}
<div class="container">
<div class="col-md-12 text-center border mt-3">
<h1 class="text-white">{{album.artist}} :: {{album.title}}</h1>
</div>
<div class="row mt-3">
<div class="col-sm-4 col-md-4 text-center">
{% if album.albumArt == None %}
<img src="/static/album_art/not_available.png" height="300" width="300">
<a class="btn btn-primary mt-3">Upload Cover</a>
{% endif %}
</div>
<div class="col-sm-8 col-md-8">
<table class="table table-light table-striped">
<tr>
<td>Artist: {{album.artist}}</td>
</tr>
<tr>
<td>Album: {{album.title}}</td>
</tr>
<tr>
<td>Catalog No: {{album.catno}}</td>
</tr>
<tr>
<td>Record Label: {{album.label}}</td>
</tr>
<tr>
<td>Year Released: {{album.year}}</td>
</tr>
<tr>
<td>Genre: {{album.genre}}</td>
</tr>
</table>
</div>
</div>
<div class="card text-center mt-3">
<div class="card-header text-center bg-primary">
<p>EDIT ALBUM</p>
</div>
<form method="POST" action="{{ url_for('edit_album', catno=album.catno) }}" class="card-footer text-center">
<div class="row">
{{ form.csrf_token}}
<div class="col-sm-4">
{{ form.artist.label }}<br>
{{ form.artist }}<br>
</div>
<div class="col-sm-4">
{{ form.title.label }}<br>
{{ form.title }}<br>
</div>
<div class="col-sm-4">
{{ form.year.label }}<br>
{{ form.year }}<br>
</div>
</div>
<div class="row">
<div class="col-sm-4">
{{ form.rlabel.label }}<br>
{{ form.rlabel }}<br>
</div>
<div class="col-sm-4">
{{ form.genre.label }}<br>
{{ form.genre }}
</div>
</div>
<p><input class="btn btn-primary mt-3" type="submit" value="Submit">
</form>
</div>
</div>
{% endblock %}
The only thing I really got from searching last night, is that I may have two connections to the DB open, but I don't since I just have the one connection at the beginning of the script. It wouldn't be an issue with too many cursors, would it?
Otherwise, this is the first app I've used the Flask-WTF module for the forms, so could it be something wrong I'm doing with that? Here's that class if there's any questions:
# Form for adding record to database
class AlbumForm(FlaskForm):
# Album Art - figure out image uploads
cover = FileField('Upload Cover Art')
catno = StringField('Catalog Number')
artist = StringField('Artist')
title = StringField("Album Title")
year = StringField('Year Released')
rlabel = StringField('Record Label')
genre = StringField('Genre')
The app doesn't throw any errors, so I'm not sure what's going on, or if I'm just overlooking something.
Seems like you are overwriting your form on post, because on both get and post you are fetching an album entry and filing a form with it's data. It should work if you structure it like this:
def edit_album(catno):
cur = mysql.connection.cursor()
if request.method == 'POST':
form = AlbumForm() # WTForms will extract data from the request's body by itself
# other code from a if request.method == 'POST' block
elif request.method == 'GET':
cur.execute("...")
album = cur.fetchone()
form = AlbumForm()
form.artist.data = album['artist']
form.title.data = album['title']
form.year.data = album['year']
form.rlabel.data = album['label']
form.genre.data = album['genre']
return render_template...
P.S. A good but too high-level and magic-y (and hard to understand as a result) example is given in the WTForms docs: wtform has formdata and obj arguments; each time wtform instance is created (form = AlbumForm) it tries to extract data from a request to populate it's fields. If it fails (and it would on a get-request because no form-data exist) it will get data from a second source -- the obj argument, which has your current db-entry value. But on post wtform successfully retrieves data from a post-request-formdata which then populates db-entry which is then saved.
The solution was this:
The value of the variables that are used to update the database were supposed to be like this:
catno = album['catno']
artist = request.form['artist']
title = request.form['title']
year = request.form['year']
rlabel = request.form['rlabel']
genre = request.form['genre']
And not:
catno = album['catno']
artist = form.artist.data
title = form.title.data
year = form.year.data
rlabel = form.rlabel.data
genre = form.genre.data
Because in the latter method, I was just passing the same data into the variables that was loaded into the form when the page was opened, instead of the updated values in the text boxes.

Weird HTML select tag behavior with python flask

HTML with data-binding
Location:<br>
{% for item in data %}
<select name="location">
<option value={{ item[0] }}>{{ item[0] }}</option>
</select>
{% endfor %}
Backend
#app.route('/events', methods = ['post', 'get'])
def events():
#data = ['loc1','loc2','loc3']
cursor = conn.cursor()
cursor.execute('SELECT * FROM location')
rows = cursor.fetchall()
data = [row for row in rows]
cursor.close()
return render_template('events.html', data = data)
when I render_template and pass in the data, it retrieves a list of locations from the database and puts it as options to select from.
This now looks like this
It's supposed to have on selection list(?) with 4 options, but there are just 4 separate selection list with on option in it.
How can I fix this?
You need to loop over the select options, not over the entire select block:
Location:<br>
<select name="location">
{% for item in data %}
<option value={{ item[0] }}>{{ item[0] }}</option>
{% endfor %}
</select>

Python. Django1.7 DoesNotExist. Matching query does not exist

I'm a learner in Python and Django.
I am trying to pass selected checkboxes to my views and then make a get() call to fetch related objects, but keep getting the error DoesNotExist, even though the object is present in the database.
I tried changing the get() parameters but it still shows the same error, as if it just cannot fetch the database. Please help!
ERROR IS IN THE #ed LINE
Here is my views.py
def manage(request):
if request.POST.get('taskname'):
name = request.POST.get('taskname')
end = request.POST.get('enddate')
emp = User.objects.get(username = request.user.username)
print emp.username
try:
newtask = Task(taskname = name, deadline = end, status = 'incomplete', empid = emp)
newtask.save()
except:
print "not saved"
my_tasks = Task.objects.filter(empid = emp)
return render(request, 'ellipse/dashboard.html', {'employee': emp, 'tasks': my_tasks})
else:
selected = request.POST.get('dropdown')
if selected == 'Delete':
tasks = request.POST.getlist('t')
emp = User.objects.get(username = request.user.username)
for seltask in tasks:
#deltask = Task.objects.get(taskname=seltask)
deltask.delete()
my_tasks = Task.objects.filter(empid = emp)
return render(request, 'ellipse/dashboard.html', {'employee': emp, 'tasks': my_tasks})
And, my html:
<div>
<form action="/ellipse/manage/" method="post">
{% csrf_token %}
<p>Taskname <input type="text" name="taskname"></p>
<p>Deadline <input type="date" name="enddate"></p>
<select name="dropdown">
<option selected="selected" disabled>Select action :</option>
<option value="Add">Add</option>
<option value="Delete">Delete</option>
<option value="Mark as complete">Mark as complete</option>
<option value="Mark as incomplete">Mark as incomplete</option>
</select>
{% if tasks %}
{% for tasko in tasks %}
<p><tr><td><input type="checkbox" name="t" value={{ tasko.taskname }}/></td><td>{{ tasko.taskname }}</td><td>{{ tasko.deadline }}</td><td>{{ tasko.status }}</td></tr></p>
{% endfor %}
{% endif %}
<p><button type="submit" name="modify">Modify</button></p>
</form>
</div>
I am clueless on how to proceed further and it'd be great help if this issue can be resolved. Thanks in advance!
Well your get looks jacked up.
emp = User.objects.get(username = request.user.username)
should probably be something like this.
emp = User.objects.get(id=request.user.id)
You could probably do this to...
emp = User.objects.get(user=request.user)

Categories

Resources