Flask flashed messages not showing - python

I'm trying to flash messages in Flask using flash(), but the messages aren't appearing on the page. It isn't in the source code for the page either when looking at it with Dev Tools.
Here is the code that I have in my base.html It is outside of the blocks:
{% with messages = get_flashed_messages(with_categories=true) %}
<p>1</p>
{% if messages %}
<p>2</p>
{% for message, category in messages %}
<p>3</p>
{% if category == 'success' %}
<p>4</p>
<div class='message success'>
<p>{{ message }}</p>
</div>
{% elif category == 'error' %}
<div class='message error'>
<p>{{ message }}</p>
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endwith %}
Python code(shortened to include relevant bits)
#app.route('/suggestion', methods=['GET', 'POST'])
def suggestion():
if request.method == 'POST':
...
content = f'Name: {name}\nEmail: {email}\nQuestion: {question}\nAnswer: {answer}\nType: {type}\nTopic: {topic}'
if sensible == 'Agreed' and accurate == 'Agreed':
email = Email()
sent = email.sendEmail(content)
if sent:
flash('Suggestion submitted successfully', category='success')
else:
flash('Error submitting suggestion. Please try again later',
category='error')
return redirect(url_for('suggest'))
Using the p tags to see where it's failing, I can tell that the {% if messages %} isn't working, but I don't know why.
I'm using flash('Message', category='success') to send the messages. I've looked at the Flask documentation and can't figure out what I'm doing wrong.
Please can someone help?

Have a look at this implementation
Routes.py
#auth.route("/login", methods=["GET", "POST"])
def login():
form = LoginForm()
if request.method == "POST":
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.confirm_password(form.password.data):
login_user(user)
flash("Login successful", "success")
return redirect(url_for("home.index"))
flash("Invalid email or password", "error")
return render_template("auth/login.html", form=form)
_message.html template
<div class="flash-message">
<div class="msg-wrapper">
{% with messages=get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category,message in messages %}
<p class="{{category}} message">{{message}}</p>
{% endfor %}
{% endif %}
{% endwith %}
</div>
</div>
Looping through the messages and categories in reverse

Related

Python Flask, displaying an input from one page on another

None of the other answers on this seem to solve my problem. I am trying to display a greeting that says "Welcome to the app [user]" when someone logs in. I am not sure how to get the greet page to display this message.
Here is my login function
#app.route("/login2", methods=["POST", "GET"])
def login():
if request.method == "POST":
session.permanent = True
user=request.form["nm"]
session["user"] = user
return render_template("greet.html")
else:
if "user" in session:
return redirect(url_for("greet"))
return render_template("login2.html")
Here is my login.html page
{% extends "base.html" %}
{% block title %}Log In Page{% endblock %}
{% block content %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for msg in messages %}
<p>{{msg}}</p>
{% endfor %}
{% endif %}
{% endwith %}
<form action="#" method="post">
<p>Name: </p>
<p><input type="text", name="nm" /></p>
<p><input type="submit", value="submit" /></p>
</form>
{% endblock %}
And here is greet.html, which should display the message that I want.
{% extends "base.html" %}
{% block content %} <h1>Welcome</h1>
<p>Hi, Welcome to the app {{}} .</p>
{% endblock %}
I believe that I need to pass something into the {{}} on the greet.html page, but I do not know what to pass in here.
In your login route when the method is POST pass the user object to the template.
#app.route("/login2", methods=["POST", "GET"])
def login():
if request.method == "POST":
session.permanent = True
user=request.form["nm"]
session["user"] = user
return render_template("greet.html", user=user)
else:
if "user" in session:
return redirect(url_for("greet"))
return render_template("login2.html")
Now you can use it in the template
<p>Hi, Welcome to the app {{user.name}} .</p>

Why is my wtforms error handling not working? [duplicate]

This question already has answers here:
Flask view return error "View function did not return a response"
(3 answers)
Closed 1 year ago.
I am trying to build a flask login and registration system. Everything works except when the user gives an incorrect input to the forms then there will be an error since there is no working error handling yet. I am using wtforms and here is the registration form class:
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=20)])
email = StringField('Email', validators=[DataRequired(),Email()])
password = PasswordField('Password', validators=[DataRequired(), Length(min=4)])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), Length(min=4), EqualTo('password')])
submit = SubmitField('Sign Up')
And this is the registration route
#app.route('/register', methods=["GET", "POST"])
def register():
form = RegistrationForm()
if request.method == "POST":
if form.validate_on_submit():
return redirect(url_for('home'))
else:
return render_template('register.html', form=form)
I have tired to handle the errors in htmlbut every time the user gives the incorrect input then it show this error message "TypeError: The view function for 'register' did not return a valid response. The function either returned None or ended without a return statement." Here is my html form:
<form action="/register" method="POST">
<h1>Create Account</h1>
{{ form.hidden_tag() }} {% if form.username.errors %} {{
form.username(placeholder="Username", class="is-invalid") }} {% for
error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %} {% else %} {{ form.username(placeholder="Username") }} {%
endif %} {% if form.email.errors %} {{ form.email(placeholder="Email",
class="is-invalid") }} {% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %} {% else %} {{ form.email(placeholder="Email") }} {% endif
%} {% if form.password.errors %} {{
form.password(placeholder="Password", class="is-invalid") }} {% for
error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %} {% else %} {{ form.password(placeholder="Password") }} {%
endif %} {% if form.confirm_password.errors %} {{
form.confirm_password(placeholder="Confirm Password",
class="is-invalid") }} {% for error in form.confirm_password.errors %}
<span>{{ error }}</span>
{% endfor %} {% else %} {{ form.confirm_password(placeholder="Confirm
Password") }} {% endif %}
<div>{{ form.submit(class="signup") }}</div>
</form>
Any response or help will be greatly appreciated. Thanks!
Every view must return something. Yours returns nothing if method is post but doesn't validate. It is a logical problem, not related to wtforms.
if request.method == "POST":
if form.validate_on_submit():
return redirect(url_for('home'))
else:
return 'oops'
else:
return render_template('register.html', form=form)

Why doesn't me flask app redirect the user?

I'm creating a flask blog. After the registration form is completed, I want to redirect the user back to the home page and show the user a message.
The problem is that the user doesn't get redirected. It only flashes once.
Python code:
#app.route("/register", methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
flash(f'Account created for {form.username.data}!')
return redirect(url_for('home'))
return render_template('register.html', title='Register', form=form)
HTML code:
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-success">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}

Django - How to give a URL a Variable

I am in the process of making a edit listing system for my website and have run into an issue, the problem I am having is with my edit listing portal which displays all the listings associated with the relevant account. The idea is that people can click on any of the listings and it will take them to the edit listing form, however my edit listing form is suppose to be given a public key when you click on it. My problem is I dont know how to put the listings pk into the url. Could somebody please advise me on what to do?
Thanks
Code -
Listings Portal -
{% extends "base.html" %}
{% block content %}
<h1 class="pageheader">Edit Your Job Listings</h1>
<div class="joblistings">
<p class="jobcounter">There are <b>{{ joblistings.count }}</b> jobs available</p>
{% if joblistings %}
{% for joblisting in joblistings %}
{% if joblisting.active_listing %}
<div class="listings-item">
<a href="{% url 'editlisting' %}"> <--- THIS IS THE URL
<ul>
<li class="listing-title">{{ joblisting.job_title }} - {{ joblisting.business_name }}</li>
<li>Region: {{ joblisting.business_address_suburb }}</li>
<li>Pay Rate: ${{ joblisting.pay_rate }}</li>
<li>Contact Method: {{ joblisting.contact_method }}</li>
</ul>
</a>
</div>
{% endif %}
{% endfor %}
{% else %}
<p>Unfortunately all of the job opportunities have been taken at this moment.</p>
{% endif %}
</div>
{% endblock %}
Edit Listing View -
# This is the view which manages the edit listing page
#login_required(redirect_field_name='login')
def editlisting(request, pk):
post = JobListing.objects.get(pk=pk)
#if str(request.user) != str(post.user):
# return redirect("index")
if request.method == "POST":
print("test")
form = JobListingForm(request.POST, instance=post, force_update=True)
if form.is_valid():
form.save()
return redirect('index')
else:
print("else")
form = JobListingForm(instance=post)
context = {
"form": form
}
return render(request, "editlisting.html", context)
How about this?
Click me

unable to show custom error message in Jinja2 template

I'm writing a register user function in ( using Flask, Python, Jinja2) which i'm checking if a username (or email) is already present and if so shows an error to below TextField.
register code is:
#app.route('/register', methods=['GET', 'POST'])
def register():
form = SignupForm()
error = None
if form.validate_on_submit():
user_by_name = Users.query.filter_by(username=form.username.data).first()
user_by_email = Users.query.filter_by(email=form.email.data).first()
if user_by_name:
error = 'Username already taken. Choose another'
return render_template('register.html', form=form, error = error)
elif user_by_email:
error = 'Email already registered. Login or register with another Email'
return render_template('register.html', form=form, error = error)
else:
#Add user details to DB logic
return redirect(url_for('index'))
return render_template('register.html', form=form, error = error)
I have a macro defined in a file util.html
{% macro render_field(field) %}
<div class="control-group {% if field.errors %}error{% endif %}">
{% if kwargs.get('label', True) %}
{{ field.label(class="control-label") }}
{% endif %}
<div class="controls">
{{ field(**kwargs) }}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
</div>
{% endmacro %}
and using this macro in register.html as:
{% from "util.html" import render_field %}
{% extends "base.html" %}
{% block content %}
<form method="post">
{{ form.hidden_tag() }}
{{ render_field(form.username, label=True, class="input-xlarge", autofocus="autofocus", errors=error) }}
{{ render_field(form.password, label=True, class="input-xlarge", autofocus="autofocus") }}
{{ render_field(form.confirm, label=True, class="input-xlarge", autofocus="autofocus") }}
{{ render_field(form.email, label=True, class="input-xlarge", autofocus="autofocus", errors=error) }}
<button class="btn" type="submit">Register</button>
</form>
{% endblock %}
Now when i test the localhost:5000/register with duplicate username or email address it doesn't show any error at all (also doesn't add any user into DB which is okay).
But when i enter any wrong email or leave any field blank it shows respective error, but not showing the error which i want to pass using register view.
Is there any Jinja2 related logic missing?
And why its showing errors related to blank field or wrong email but not which i try to pass on duplicate username etc.
Please suggest.
Well, you doing it wrong :)
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
This macro searches for error in respective field.errors
But you pass error context variable, which is not attached to the field.
The right way to solve this will be to add def validate_user to your form definition and check for everything in there.
If it goes wrong -> raise ValidationError(message)
See example here:
WTForms documentation
With this approach, your validate_on_submit() should not return True if it is not validated.
You can just flash the error like this
sample code
file: views.py
#app.route('/')
def index():
# some checks which provided error
if error:
flash(error)
return render_template('template.html')
file template.html
{% for category, msg in get_flashed_messages(with_categories=true) %}
<div class="category">{{ msg|safe }}</div>
{% endfor %}

Categories

Resources