In my routes.py I set a variable to the converted dictionary generated from SQLAlchemy tuples right after the form validation statement.
When typing from routes import *
dict(Book.query.with_entities(Book.username, Book.choice).all()) in console i get the correct dictionary as wanted {'user1': 'choice1', 'user2': 'choice2'}
If I type the name of the variable dict_of_users assiged to this dictionary I get: NameError: name 'dict_of_users' is not defined
Why it does not recognise that variable since it is in the code?
The logic behind I want to achieve:
If the user select one choice from available in the list, that user and its choice are added as key and value in the dictionary, otherwise the dictionary is empty.
My routes.py:
#app.route("/booking", methods=['POST', 'GET'])
def booking():
session.permanent = True
app.permanent_session_lifetime = timedelta(seconds=5)
form = BookingForm()
if form.validate_on_submit():
book = Book(username=current_user.username, choice=form.book.data)
db.session.add(book)
db.session.commit()
flash('Your choice is registered', 'success')
dict_of_users = dict(Book.query.with_entities(Book.username, Book.choice).all())
return render_template('booking.html', title='Booking', form=form, dict_of_users=dict_of_users)
If it's only inside of the function, you can't access it outside of the function. Since the variable is only defined in the function, you get the NameError message. A fix is to define the variable in the global scope.
EDIT:
As a response to your comment:
if you want to access the dict_of_users variable, declare it outside of the function. Then the variable will contain the value of it's latest use in the global scope, and thus accesible outside of the function.
Something like this should do the trick:
dict_of_users = None
#app.route("/booking", methods=['POST', 'GET'])
def booking():
session.permanent = True
app.permanent_session_lifetime = timedelta(seconds=5)
form = BookingForm()
if form.validate_on_submit():
book = Book(username=current_user.username, choice=form.book.data)
db.session.add(book)
db.session.commit()
flash('Your choice is registered', 'success')
dict_of_users = dict(Book.query.with_entities(Book.username, Book.choice).all())
return render_template('booking.html', title='Booking', form=form, dict_of_users=dict_of_users)
Related
This question already has answers here:
Python: Assign Value if None Exists
(9 answers)
Closed 1 year ago.
I want to access couple of variables from if-block, outside in the function
eg: i want to use signin, user
#app.route('/signup', methods=['GET', 'POST'])
def register():
form1 = Signup()
if form1.validate_on_submit():
signin = auth_py.create_user_with_email_and_password(form1.email_address.data, form1.password.data)
user = auth_py.send_email_verification(signin['idToken']) # for email verification
name = form1.name.data
username = form1.username.data
email_address = form1.email_address.data
return redirect(url_for('home_page'))
if form1.errors != {}: # if no errors occur from validators
for err_msg in form1.errors.values():
print(f'there was an error creating the user {err_msg}')
database(username, name, email_address) # problem is here
return render_template('sign-up.html', form1=form1)
I want to use name, username and email_address from form1.validate_on_submit() inside database() and i don't know how can i do that.
NOTE: there is some code yet to be written in main program so I cannot call database() function inside form1.validate_on_submit()
signin = None;
user = None;
def register():
form1 = Signup()
if form1.validate_on_submit():
signin = auth_py.create_user_with_email_and_password(form1.email_address.data, form1.password.data)
user = auth_py.send_email_verification(signin['idToken']) # for email verification
name = form1.name.data
username = form1.username.data
email_address = form1.email_address.data
return redirect(url_for('home_page'))
if form1.errors != {}:`enter code here`
Define variable outside your if-block, this way you can use the
variables outside the if-block.
I want checkboxes on my website. If these checkboxes are selected, an output should be output. If the checkboxes are not selected, nothing should happen.
I almost made it. But I don't know how to program that if the checkbox is not selected, nothing happens
Here is my try in my Python (flask):
#app.route("/checkbox", methods = ['GET','POST'])
def checkbox_value():
if request.method == 'POST':
if request.form.get("checkbox1"):
checkbox_data_1 = some_data
checkbox_title_1 = some_other_data
else:
#nothing should happen.
if request.form.get("checkbox2"):
checkbox_data_2 = some_data
checkbox_title_2 = some_other_data
else:
#nothing should happen.
return render_template('index.html', checkbox_data_1= checkbox_data_1, checkbox_title_1= checkbox_title_1, checkbox_data_2= checkbox_data_2, checkbox_title_2= checkbox_title_2 )
If I don't select a checkbox I get this error message "UnboundLocalError: local variable 'checkbox_data_1' referenced before assignment"
That error means that you are referencing a variable before it is declared.
In the case where checkbox 1 is not selected, you will be referencing checkbox_data_1 and checkbox_title_1 in the return statement when they have not been declared since the code does not enter the first if block. Same goes for checkbox 2.
To resolve this, simply initialize them with some default value. I went ahead and declared it as None but go ahead and change it to what works for you.
#app.route("/checkbox", methods = ['GET','POST'])
def checkbox_value():
checkbox_data_1 = None
checkbox_title_1 = None
checkbox_data_2 = None
checkbox_title_2 = None
if request.method == 'POST':
if request.form.get("checkbox1"):
checkbox_data_1 = some_data
checkbox_title_1 = some_other_data
if request.form.get("checkbox2"):
checkbox_data_2 = some_data
checkbox_title_2 = some_other_data
return render_template('index.html', checkbox_data_1= checkbox_data_1, checkbox_title_1= checkbox_title_1, checkbox_data_2= checkbox_data_2, checkbox_title_2= checkbox_title_2 )
Also, there is no need for an else block if you're going to leave it empty
Trying to retrieve an int from a function which get the data from a form in wtform in Flask.
form.py
class CoilsSlittingMetric(FlaskForm):
masterCoil = IntegerField('Master Coil Size [mm]', validators=[DataRequired()])
slitOne = IntegerField('First Coil Size [mm]', validators=[DataRequired()])
slitTwo = IntegerField('Second Coil Size [mm]', validators=[DataRequired()])
slitThree = IntegerField('Third Coil Size [mm]', validators=[DataRequired()])
slitFour = IntegerField('Fourth Coil Size [mm]', validators=[DataRequired()])
remember = BooleanField('Remember my current entries?')
submit = SubmitField('Calculate!')
when I run the routes.py without the return a statement it shows the flash message just fine
but when I try to return the (myproblem) integer it returns the following error
TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple,
here is the function
#app.route('/slitter', methods=['GET', 'POST'])
#login_required
def slitter():
form = CoilsSlittingMetric()
if form.validate_on_submit():
myproblem = form.masterCoil.data
flash(myproblem)
flash(f'Calculating {form.masterCoil.data} '
f'and resulting data {form.slitOne.data}, {form.slitTwo.data}, '
f'{form.slitThree.data}, {form.slitFour.data}')
return myproblem
return redirect(url_for('slitter_results'))
return render_template('slitter.html', title="Slitter Calculator - Metric Sizes", form=form)
I sort of understand what is says in the error message but I need to use the integers of each of the values (testing just with one of them to simplify) but I don't know how to do it.
I tried to search for similar issues in here but did find only one solution which did not work for me.
EDIT:
I try to use this value(s) later in another function
#app.route('/slitter_results', methods=['GET', 'POST'])
#login_required
myproblem = slitter()
flash(myproblem)
I think you are looking for something like this:
First, get the value from the form submitted and then pass the value in slitter_results function
#app.route('/slitter', methods=['GET', 'POST'])
#login_required
def slitter():
form = CoilsSlittingMetric()
if form.validate_on_submit():
myproblem = form.masterCoil.data
flash(f'Calculating {form.masterCoil.data} '
f'and resulting data {form.slitOne.data}, {form.slitTwo.data}, '
f'{form.slitThree.data}, {form.slitFour.data}')
return redirect(url_for('slitter_results', param_int=myproblem))
return render_template('slitter.html', title="Slitter Calculator - Metric Sizes", form=form)
slitter_results function will look like this:
#app.route('/slitter_results/<int: param_int>', methods=['GET', 'POST'])
#login_required
def slitter_results(param_int)
myproblem = param_int
flash(myproblem)
return "Yay" #just so you don't get an error, you can render or redirect to anywhere from here!
For more info have a look at Variable Rules and URL Building
Here I am sharing an example code of what i am trying to achieve.
my_bluprint = Blueprint('index',
__name__,
template_folder=template_dir)
#my_bluprint.route('/print', methods=['GET', 'POST'])
def my_function_2():
print('i was redirected')
if request.method == 'POST':
age = request.form.get('age')
print('AGE: ', age)
return render_template("form2.html")
#my_bluprint.route('/test', methods=['GET', 'POST'])
def my_function():
if request.method == 'POST':
print('my_function')
# do something
name = request.form.get('name')
print('my_name', name)
if name == 'root':
print('name is ', name)
return redirect(url_for("index.my_function_2"))
# age = request.form.get('age')
print('AGE: ',age) # I need input age from my_function_2 here
age_trans = my_module.ageMul(age)
print('TransAGE: ', age_trans)
return render_template("result.html", result=age_trans)
return render_template("form1.html")
I need to render different templates depending on the input from previous template.
On run time my program will use the input from one template to decide which template to redirect next. I tried rendering the templates the way i have used in my example code but I need inputs from previous templates for further processing combined with inputs of all the other templates which were rendered.
EDIT
i am able to redirect to other routes in my code. but i need input from the template i am using in my_function_2() in my_function() after the execution of my_function_2(). which means i need to come back to main route i-e /test with data from my_function_2. I need help in understanding how can I do that
Another Idea
is there a way to render different templates using conditions in same function lets say my_function(). If input from one html form makes the condition true render template A else render template B ? meanwhile retaining the inputs from first template rendered in my_function()? in this way i can have only one route rendering multiple templates ? but i want to keep data from all the templates previously rendered
what would be the good approach of doing this ?
EIDT 2
i tried this
#my_bluprint.route('/test', methods=['GET', 'POST'])
def my_function():
if request.method == 'POST':
#name = request.form.get('name')
session['name'] = request.form['name']
print('my_name', session['name'])
if session['name'] == 'root':
print('name is ', session['name'])
#return redirect(url_for("index.my_function_2"))
return render_template("form2.html")
age = request.form.get('age')
print('AGE ',age)
age_trans = my_module.ageMul(age)
print('TransAGE: ', age_trans)
print(session['name'])
return render_template("result.html", result=age_trans)
return render_template("form1.html")
First run goes smooth till return render_template("form2.html") after the form submitted here control goes back to if request.method == 'POST': and execute it from the start and gives me error here session['name'] = request.form['name'] but i want to the program control to always move forward with the values it got in first run of render_template("form1.html") until the page(url) is refreshed
You can pass it in query param in redirect or store it in session.
I'm making a web application, where user action can affect some bar graphs (seen in the gif below). Sometimes, changes aren't saved. When I reload the page, the changed bar graphs are shown (indicating that the user's action's were saved). When I reload the page again, sometimes the updated bar graphs and corresponding list are shown. Other times, they are not.
Here's the code for the view:
#app.route('/')
def home():
'''homepage for application'''
# redirect users who go to home page but aren't logged in
if not current_user.is_authenticated:
return redirect(url_for("landing"))
# reset the session
db.session.flush()
# get most recent entered weight
try:
last_weight = WeightEntry.query.filter_by(user_id = current_user.user_id).order_by(WeightEntry.date)[-1]
except IndexError:
return error("No weight recorded. Please contact support.")
return render_template("home.html",
today= Today(current_user.user_id),
foods = [food for food in FoodEntry.query.filter_by(user_id=current_user.user_id).all() if food.is_today() == True],
options = sorted(Food.query.filter(Food.user_id==current_user.user_id).all(), key=lambda x: x.name),
last_weight = last_weight)
I added the db.session.flush() in an attempt to solve the problem, but that didn't work.
The changes (logged foods) are stored here:
#app.route("/log_food", methods=["POST", "GET"])
#login_required
def log_food():
# add foods given by the user
if request.method == "POST":
for food in request.form.getlist("logged_food"):
try:
added_food = Food.query.filter_by(user_id=current_user.user_id, name=food).first()
x = FoodEntry(
food_id = added_food.food_id,
user_id = current_user.user_id)
db.session.add(x)
db.session.commit()
except:
return error("Unable to log food.")
return redirect(url_for("home"))
I'd appreciate any help I can get.
Thanks!
I fixed it by adding db.session.commit() to the page functions.
For example, for the homepage: I did:
#app.route('/')
def home():
'''homepage for application'''
db.session.commit()
...