How to flash success and danger with different messages in flask. - python

I have a flask application where I want to flash different alert messages depending on an action.
here is my first message, where i check if an email matches my regex pattern:
reciver = str(email)
if not re.match(r"[^#]+#[^#]+\.[^#]+", reciver):
flash("Please enter a valid email address", 'error')
return render_template("about.html")
here is the second message, which is displayed if a message is sent successfully:
flash('Message sent succesfully', 'succes')
return render_template("about.html")
here is my HTML code:
<h1 class="mb-5"> Enter your message, and i will get back to you as soon as possible</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-success">
<li>{{ message }} </li>
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
how can I make an alert-danger for the first message and an alert-success for the second message, is there some sort of conditional that can be used?

You can use the following pattern to specify the category parameter of the flash function.
:param category: the category for the message. The following values
are recommended: 'message' for any kind of message,
'error' for errors, 'info' for information
messages and 'warning' for warnings. However any
kind of string can be used as category.
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert {{ category }}"> {{ message|capitalize }} </div>
{% endfor %}
{% endif %}
{% endwith %}
By putting category in the class attribute, you can associate special colors with some css rules like :
.alert.success {
background-color: green;
}
.alert.error {
background-color: red;
}
flash('Message sent successfully', 'success')
flash("Please enter a valid email address", 'error')
These calls will generate:
<div class="alert success"> Message sent successfully </div>
<div class="alert error"> Please enter a valid email address </div>
Official documentation : http://flask.pocoo.org/docs/1.0/patterns/flashing/#flashing-with-categories

With flask 1.0.2 this similar but slightly different approach worked for me - slightly simpler I think:
flash('This is an error message in red', 'danger')
flash('This is an informational message in blue', 'info')
In Flask HTML template:
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}" role="alert"> {{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
This way I didn't need to define any CSS and just used what was already in the default Flask distribution.

Related

Error message not working as expected in Django

I am trying to display a message on order creation success or failure. For messages.success(request, "My message") it is working as expected. But for messages.error(request, "My message") it is not as expected. I read the django messages framework docs, but no use. Can someone tell me why is this happening
Success Message:
Failed Message:
This is supposed to be red alert if I am not wrong.
Here's my html file.
base.html
<main role="main" class="container" >
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
views.py
if verify:
if response_dict['RESPCODE'] == '01':
messages.success(
request, "Thank you for ordering! Your items will be delivered soon")
return redirect(reverse('update-records', kwargs={'order_id': order_id}))
else:
messages.error(
request, "Your order could not be placed, here are the details: " + response_dict['RESPMSG'])
return redirect(reverse('profile-page'))
If the problem is alert-error not working you can use this after have the import statement of your message :
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.ERROR: 'danger'
}
Reference ->
https://docs.djangoproject.com/en/3.0/ref/contrib/messages/#message-tags
#Sowjanya R Bhat
The method you suggest can be hardcoded but I need to know, why isn't it implementing red alert my default. Your suggestion works however
<main role="main" class="container" >
{% if messages %}
{% for message in messages %}
{% if message.tags == "error"%}
<div class="alert alert-danger">
{{ message }}
</div>
{% else %}
<div class="alert alert-success">
{{ message }}
</div>
{% endif %}
{% endfor %}
{% endif %}
In your HTML:
<script>
setTimeout(function () {
$('#flash').fadeOut('fast');
},5000);
</script>
<div id="flash">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags}} m-0" role="alert">
<strong>{{ message }}</strong>
</div>
{% endfor %}
{% endif %}
</div>
in django settings.py:
from django.contrib.messages import constants as messages
MESSAGE_TAGS = {
messages.ERROR: 'danger'
}
in django views:
from django.contrib import messages
if verify:
if response_dict['RESPCODE'] == '01':
messages.success(
request, "Thank you for ordering! Your items will be delivered soon")
return redirect(reverse('update-records', kwargs={'order_id': order_id}))
else:
messages.error(
request, "Your order could not be placed, here are the details: " + response_dict['RESPMSG'])
return redirect(reverse('profile-page'))
just use messages.warning instead, it would at least show a color.
This is because alert-error is not a bootstrap class.
The according class is named alert-danger.
Generally the tags line up nicely between bootstrap and django, this is why your code works. But as you see "error" != "danger".
To fix the issue replace
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
with
{% if message.tags == "error" %}
<div class="alert alert-danger">
{{ message }}
</div>
{% else %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endif %}

Create pop up message in django

I am doing some calculations in my views.py and I want to show the result.
I have tried to use the following:
return render(request, index.html{message:variable})
and
return HttpResponse(message)
I want to show the result as a Popup message. How can I implement this?
first you have to render template by
return render_template( "example.html",message = any_variable)
and then you can show pop up on html via java script by
<script>
alert("This is alert box!"); // display string message
alert( {{message}} ); // display python variable
</script>
although i recommend using jinja as template
You can use Django messages https://docs.djangoproject.com/en/3.2/ref/contrib/messages/
from django.contrib import messages
messages.success(request, 'Success')
In your template, use something like:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}

How to send Json or "dict" using Django Messages Framework

I'm using Django Messaging framework to send additional data on the validation error:
def clean_X(self):
xuser_id = self.cleaned_data['xuser_id']
if xuser.objects.filter(xuser_id=xuser_id).exists():
available_now = {"available" : ["example","hello","ahc","sdcsd"]}
messages.error(self.request, message = available_now,extra_tags="available_ids")
raise forms.ValidationError('Sorry! User ID "%(xuser_id)s" is already taken, Please try another or chose one from following:', params={"xuser_id" : xuser_id})
return xuser_id
The message is converted as a string when tried to access in the template: like
"{"available" : ["example","hello","ahc","sdcsd"]}"
making difficult to access programmatically i.e message.available
How can i send a json directly to the template using Django-Messages. My intention is here, not just to display a message rather make available-id's clickable (like the one in gmail auto-suggestion of username)
Thanks!
{% for message in messages %}
<p>{{ message.tags }}</p>
{% if message.tags == 'available_ids error' %}
{% for obj,values in message.message.items %}
<div>
{{ obj }}
{% for val in values %}
<p class="user-id">{{ val }}</p>
{% endfor %}
</div>
{% endfor %}
{% endif %}
{% endfor %}
You can use above code snippet inside template to make it working and modify it according to your requirements.
How it works?
We iterate through each and every message, as we have inserted dictionary in messages so we have to iterate dictionary and inside dictionary we have list so we have to iterate that too.
Therefore we have to use three for loop.
You have to apply some conditions like when you have to iterate? You can check using this by tags.
Here I have hard coded (iterating condition) for this purpose.
Edit:
Using two for loops
Update your clean_X with these lines
available_now = ["example","hello","ahc","sdcsd"]
messages.error(self.request, message = available_now,extra_tags="available_ids")
and use these lines in templates
{% for message in messages %}
<p>{{ message.tags }}</p>
{% if message.tags == 'available_ids error' %}
<div>
{% for val in message.message %}
<p class="user-id">{{ val }}</p>
{% endfor %}
</div>
{% endif %}
{% endfor %}

Flask: Flash function ignoring the 'category' argument

So I write the controller:
#app.route('/')
def index():
flash('Hello world!', 'success')
return render_template('index.html')
then in my template I output the flash messages like this:
{%- with messages = get_flashed_messages(with_categories=true) -%}
{%- if messages -%}
<ul class="flashes unstyled">
{%- for category, message in messages -%}
<li class="alert alert-{{ category }}">
<a class="close" data-dismiss="alert">×</a>
{{ message }}
</li>
{%- endfor -%}
</ul>
{%- endif -%}
{%- endwith %}
But the issue is that I ALWAYS get just 'message' category so <li> goes with classes 'alert alert-message'.
I read the docs and as to me I did everything right, but 'flash' function ignoring the second argument and always uses the default value 'message' (instead of given by me 'success').
I wonder if anyone had that issue and know how to handle it?
Edit: Based on other comments and testing the kwarg is unnecessary.
Based on the docs at http://flask.pocoo.org/docs/api/#message-flashing it appears you need to use this format. flash(message, category='message')
#app.route('/')
def index():
flash('Hello world!', category='success')
return render_template('index.html')
When you call get_flashed_messages(with_categories=True), it return a list of tuples in the form (category, message).
So now you can use flash() like this:
flash('some message', 'success') # `category=` is needn't
In html, you can just loop the message in the call:
{% for message in get_flashed_messages(with_categories=True) %}
<div class="alert alert-{{ message[0] }}">
<button type="button" class="close" data-dismiss="alert">×</button>
{{ message[1] }}
</div>
{% endfor %}

WTForms getting the errors

Currently in WTForms to access errors you have to loop through field errors like so:
for error in form.username.errors:
print error
Since I'm building a rest application which uses no form views, I'm forced to check through all form fields in order to find where the error lies.
Is there a way I could do something like:
for fieldName, errorMessage in form.errors:
...do something
The actual form object has an errors attribute that contains the field names and their errors in a dictionary. So you could do:
for fieldName, errorMessages in form.errors.items():
for err in errorMessages:
# do something with your errorMessages for fieldName
A cleaner solution for Flask templates:
Python 3:
{% for field, errors in form.errors.items() %}
<div class="alert alert-error">
{{ form[field].label }}: {{ ', '.join(errors) }}
</div>
{% endfor %}
Python 2:
{% for field, errors in form.errors.iteritems() %}
<div class="alert alert-error">
{{ form[field].label }}: {{ ', '.join(errors) }}
</div>
{% endfor %}
For anyone looking to do this in Flask templates:
{% for field in form.errors %}
{% for error in form.errors[field] %}
<div class="alert alert-error">
<strong>Error!</strong> {{error}}
</div>
{% endfor %}
{% endfor %}
With ModelFormFields in SqlAlchemy when used with WTForms, if you have a nested object inside an object (foreign key relationships), here is how you show the relevant errors for fields properly.
Python side:
def flash_errors(form):
for field, errors in form.errors.items():
if type(form[field]) == ModelFormField:
for error, lines in errors.iteritems():
description = "\n".join(lines)
flash(u"Error in the %s field - %s" % (
#getattr(form, field).label.text + " " + error,
form[field][error].label.text,
description
))
else:
for error, lines in errors.iteritems():
description = "\n".join(lines)
flash(u"Error in the %s field - %s" % (
#getattr(form, field).label.text + " " + error,
form[field].label.text,
description
))
Jinja side:
{% with messages = get_flashed_messages(with_categories=true) %}
{% for message in messages %}
{% if "Error" not in message[1]: %}
<div class="alert alert-info">
<strong>Success! </strong> {{ message[1] }}
</div>
{% endif %}
{% if "Error" in message[1]: %}
<div class="alert alert-warning">
{{ message[1] }}
</div>
{% endif %}
{% endfor %}
{% endwith %}
Hope that helps.

Categories

Resources