search
  • Sign In
  • Sign Up
Password reset successful

Follow the proiects vou are interested in andi aet the latestnews about them taster

Table of Contents
Overview
Core principles
gradually realized
1. Flask backend logic modification (server.py)
2. Jinja2 front-end template integration (index.html)
3. Complete sample code
Notes and advancements
Summarize
Home Web Front-end HTML Tutorial Implement success/error message display after form submission in Flask application

Implement success/error message display after form submission in Flask application

Nov 20, 2025 pm 10:00 PM

Implement success/error message display after form submission in Flask application

This article details how to dynamically display success or error messages after form submission in a Flask web application by combining back-end Python logic and front-end Jinja2 template engine. This method uses server-side variables for conditional rendering, avoids dependence on client-side JavaScript, provides a concise and efficient feedback mechanism, and covers back-end error handling and front-end template integration.

Overview

In web development, providing immediate feedback after the user submits the form is the key to improving the user experience. This tutorial will guide you on how to display a success or error message after a form submission in a Python app based on Flask and Jinja2 without the need for complex JavaScript. We will modify the Flask back-end logic to process form data and send emails, and then use the Jinja2 template engine to dynamically render corresponding messages on the front-end based on the back-end processing results.

Core principles

The core idea of ​​implementing feedback messages after form submission is:

  1. Back-end processing: Flask routing receives form data and executes business logic (such as sending emails).
  2. Status passing: According to the execution result of the business logic (success or failure), a status variable (such as msg_status or is_success) is passed to the rendered HTML template.
  3. Front-end rendering: After receiving the status variable, the Jinja2 template uses conditional statements ({% if %}) to decide whether to display a success message or an error message.

gradually realized

We will optimize and expand based on existing code.

1. Flask backend logic modification (server.py)

First, we need to handle the form submission in the Flask application and set a state variable based on the email result. To better differentiate between success and failure, we can pass a string representing the status of the message, or two separate boolean variables. Here we use the method of passing a message_type and message_text, so that the displayed content can be controlled more flexibly.

 from flask import Flask, render_template, request

# It is recommended to store sensitive information such as email and password in environment variables or configuration files MY_EMAIL = "your_email@example.com"
MY_PASSWORD = "your_app_password" # If you use Gmail, you need to generate an application-specific password app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def home():
    message_type = None # 'success' or 'error'
    message_text = None

    if request.method == "POST":
        data = request.form
        name = data.get("name")
        email = data.get("email")
        phone = data.get("phone")
        message = data.get("message")

        # Simple data validation if not all([name, email, phone, message]):
            message_type = 'error'
            message_text = 'Please fill in all required fields. '
        else:
            try:
                with smtplib.SMTP("smtp.gmail.com", port=587) as connection:
                    connection.starttls() # Start TLS encryption connection.login(user=MY_EMAIL, password=MY_PASSWORD)
                    connection.sendmail(
                        from_addr=MY_EMAIL,
                        to_addrs=MY_EMAIL, # can be changed to the recipient’s email address msg=f"Subject:New Message from {name}\n\n"
                            f"Name: {name}\n"
                            f"Email: {email}\n"
                            f"Phone: {phone}\n"
                            f"Message: {message}"
                    )
                message_type = 'success'
                message_text = 'Your message has been sent successfully! Thank you for your contact. '
            except Exception as e:
                print(f"Failed to send email: {e}")
                message_type = 'error'
                message_text = 'An error occurred while sending the message, please try again later. '

    # Pass the message type and content when rendering the template return render_template("index.html", message_type=message_type, message_text=message_text)

if __name__ == "__main__":
    app.run(debug=True)

Code modification instructions:

  • Error handling: Added a try-except block to capture exceptions that may be thrown by smtplib, ensuring that even if the email fails to be sent, a friendly feedback can be given to the user.
  • Data Validation: Added a simple if not all([...]) check to ensure all form fields are filled in.
  • Status variables: message_type ('success' or 'error') and message_text are defined to store feedback information.
  • Template rendering: The render_template function now passes message_type and message_text to index.html.

2. Jinja2 front-end template integration (index.html)

Next, we need to modify the index.html file and use the conditional rendering function of Jinja2 to display the messages passed by the backend. We will use Bootstrap’s alert component to beautify the message display.

Find the original div elements in index.html used to display success and error messages:

 <!-- Submit success message-->
<div class="d-none" id="submitSuccessMessage">
    <div class="text-center text-white mb-3">
        <div class="fw-bolder">Form submission successful!</div>
    </div>
</div>
<!-- Submit error message-->
<div class="d-none" id="submitErrorMessage"><div class="text-center text-danger mb-3">Error sending message!</div></div>

Replace this with the following Jinja2 conditional rendering code:

 <!-- Feedback Messages -->
{% if message_type %}
    <div class="text-center mb-3">
        {% if message_type == 'success' %}
            <div class="alert alert-success" role="alert">
                <div class="fw-bolder">{{ message_text }}</div>
            </div>
        {% elif message_type == 'error' %}
            <div class="alert alert-danger" role="alert">
                <div class="fw-bolder">{{ message_text }}</div>
            </div>
        {% endif %}
    </div>
{% endif %}

<!-- Submit Button (remain unchanged) -->
<div class="text-center">
    <button class="btn btn-primary btn-xl text-uppercase" id="submitButton" type="submit">Send Message</button>
</div>

Code modification instructions:

  • External condition judgment: {% if message_type %} ensures that the message area is rendered only when the backend passes the message type. When the page is first loaded (GET request), message_type is None, so no message is displayed.
  • Internal condition judgment: {% if message_type == 'success' %} and {% elif message_type == 'error' %} choose to display success or error messages based on the value of message_type.
  • Bootstrap style: Use alert alert-success and alert alert-danger classes to display green success prompts and red error prompts respectively.
  • Message content: {{ message_text }} will directly display the specific message text passed by the backend.

3. Complete sample code

server.py

 from flask import Flask, render_template, request
import smtplib

# It is recommended to store sensitive information such as email and password in environment variables or configuration files MY_EMAIL = "your_email@example.com" # Replace with your sending email address MY_PASSWORD = "your_app_password" # Replace with your application-specific password (required for Gmail)

app = Flask(__name__)

@app.route('/', methods=["GET", "POST"])
def home():
    message_type = None # 'success' or 'error'
    message_text = None

    if request.method == "POST":
        data = request.form
        name = data.get("name")
        email = data.get("email")
        phone = data.get("phone")
        message = data.get("message")

        # Simple data validation if not all([name, email, phone, message]):
            message_type = 'error'
            message_text = 'Please fill in all required fields. '
        else:
            try:
                with smtplib.SMTP("smtp.gmail.com", port=587) as connection:
                    connection.starttls()
                    connection.login(user=MY_EMAIL, password=MY_PASSWORD)
                    connection.sendmail(
                        from_addr=MY_EMAIL,
                        to_addrs=MY_EMAIL, # can be changed to the recipient's email address, or a fixed notification email address msg=f"Subject:New Message from {name}\n\n"
                            f"Name: {name}\n"
                            f"Email: {email}\n"
                            f"Phone: {phone}\n"
                            f"Message: {message}"
                    )
                message_type = 'success'
                message_text = 'Your message has been sent successfully! Thank you for your contact. '
            except smtplib.SMTPAuthenticationError:
                print("SMTP authentication failed, please check your email and application password.")
                message_type = 'error'
                message_text = 'Failed to send email: Authentication error, please contact the website administrator. '
            except smtplib.SMTPException as e:
                print(f"Failed to send email: {e}")
                message_type = 'error'
                message_text = f'Failed to send email: {e}, please try again later. '
            except Exception as e:
                print(f"An unknown error occurred: {e}")
                message_type = 'error'
                message_text = 'An unknown error occurred, please try again later. '

    return render_template("index.html", message_type=message_type, message_text=message_text)

if __name__ == "__main__":
    app.run(debug=True)

index.html (contains only key changes to the contact form section)

 <!-- Contact-->
<section class="resume-section" id="contact">
    <div class="container">
        <div class="resume-section-content">
            <h2 class="mb-0">Contact Me</h2>
            <div class="subheading mb-5">
            If you are interested in me, I would love to hear it.
            </div>
        </div>
        <form id="contactForm" action="%7B%7B%20url_for('home')%20%7D%7D" method="post">
            <div class="row align-items-stretch mb-5">
                <div class="col-md-6">
                    <div class="form-group">
                        <!-- Name input-->
                        <input class="form-control" id="name" name="name" type="text" placeholder="Your Name *" data-sb-validations="required">
                        <div class="invalid-feedback" data-sb-feedback="name:required">A name is required.</div>
                    </div>
                    <div class="form-group">
                        <!-- Email address input-->
                        <input class="form-control" id="email" name="email" type="email" placeholder="Your Email *" data-sb-validations="required,email">
                        <div class="invalid-feedback" data-sb-feedback="email:required">An email is required.</div>
                        <div class="invalid-feedback" data-sb-feedback="email:email">Email is not valid.</div>
                    </div>
                    <div class="form-group mb-md-0">
                        <!-- Phone number input-->
                        <input class="form-control" id="phone" name="phone" type="tel" placeholder="Your Phone *" data-sb-validations="required">
                        <div class="invalid-feedback" data-sb-feedback="phone:required">A phone number is required.</div>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group form-group-textarea mb-md-0">
                        <!-- Message input-->
                        <textarea class="form-control" id="message" name="message" placeholder="Your Message *" data-sb-validations="required"></textarea>
                        <div class="invalid-feedback" data-sb-feedback="message:required">A message is required.</div>
                    </div>
                </div>
            </div>

            <!-- Feedback Messages -->
            {% if message_type %}
                <div class="text-center mb-3">
                    {% if message_type == 'success' %}
                        <div class="alert alert-success" role="alert">
                            <div class="fw-bolder">{{ message_text }}</div>
                        </div>
                    {% elif message_type == 'error' %}
                        <div class="alert alert-danger" role="alert">
                            <div class="fw-bolder">{{ message_text }}</div>
                        </div>
                    {% endif %}
                </div>
            {% endif %}

            <!-- Submit Button-->
            <div class="text-center">
                <button class="btn btn-primary btn-xl text-uppercase" id="submitButton" type="submit">Send Message</button>
            </div>
        </form>
    </div>
</section>

Notes and advancements

  1. Security:
    • Email Password: Email passwords should never be hardcoded directly into the code. Sensitive information should be managed using environment variables, configuration files, or Flask configuration objects.
    • Error messages: Avoid displaying detailed backend error messages directly on the front end, especially errors involving system paths or internal logic. Just display a user-friendly general error message.
  2. User experience:
    • Form reset: After a successful submission, form fields may need to be cleared. This usually requires some JavaScript to implement, or a redirect to a new page on the backend.
    • Message disappears: Messages usually disappear automatically after a period of time, or the user can close them manually. This requires JavaScript to implement.
  3. Flash messages (recommended):
    • For this one-time display of messages, Flask provides a flash message mechanism. It allows you to store the message after the request ends and display it on the next request (usually the one after a redirect). This is useful for avoiding double submissions of forms and achieving cleaner URLs.
    • The general process of using flash:
      1. In Flask routing, flash('message content', 'message type') is used to store messages.
      2. Then use redirect(url_for('home')) to redirect to the home page.
      3. In index.html, use {% with messages = get_flashed_messages(with_categories=true) %} to traverse and display the messages.
    • This approach is more consistent with web application best practices than passing variables directly.
  4. Client-side validation: While this tutorial focuses on server-side feedback, client-side JavaScript validations (such as Bootstrap’s built-in data-sb-validations property) are still very important to catch simple errors before the data is sent to the server, providing more immediate user feedback.

Summarize

Through this tutorial, you have learned how to leverage Flask's backend processing capabilities and Jinja2's template rendering capabilities to display a clear success or error message to the user after a form is submitted. This server-side method is simple and effective, especially suitable for scenarios that do not require complex real-time interaction. Combined with proper error handling and user experience considerations, you can provide users with a friendlier and more reliable web application experience. For more advanced requirements, such as message persistence and avoiding repeated submissions, it is recommended to further study Flask's flash message mechanism.

The above is the detailed content of Implement success/error message display after form submission in Flask application. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

ArtGPT

ArtGPT

AI image generator for creative art from text prompts.

Stock Market GPT

Stock Market GPT

AI powered investment research for smarter decisions

Popular tool

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to correctly migrate jQuery's drag and drop events to native JavaScript How to correctly migrate jQuery's drag and drop events to native JavaScript Mar 06, 2026 pm 05:15 PM

This article explains in detail the key pitfalls when migrating jQuery drag-and-drop logic (such as dragover/dragleave) to Vanilla JS - especially the problem of misuse of e.originalEvent causing dataTransfer failure, and provides directly runnable fixes and best practices.

How to make the images in a div fill with no margins while retaining the inner margins of the text How to make the images in a div fill with no margins while retaining the inner margins of the text Mar 07, 2026 pm 10:54 PM

This article explains how to keep the overall padding of the container so that the internal images are displayed close to the edge of the container, while the text content still maintains normal padding - the core is to separate the style scope and achieve precise layout through positioning and box model control.

Solve the problem of unexpected offset of Flex container due to the font size change of the first child element Solve the problem of unexpected offset of Flex container due to the font size change of the first child element Mar 09, 2026 pm 08:15 PM

When the first child element of a Flex container dynamically adjusts the font-size, the container will be vertically offset along the inline baseline; while a normal block-level container will change in height due to the linkage between line height and font measurement. The root cause lies in the baseline alignment mechanism of the Flex container. By default, the baseline of the first child is the container baseline. This can be completely solved through vertical-align: top or explicit baseline control.

Chart.js complete implementation solution for dynamically switching chart types (line chart, bar chart, pie chart) Chart.js complete implementation solution for dynamically switching chart types (line chart, bar chart, pie chart) Mar 12, 2026 pm 08:51 PM

This article explains in detail how to safely and reliably dynamically switch chart types (line/bar/pie) in Chart.js, and solve the problem of Cannot read properties of undefined errors caused by mismatched data structures and rendering exceptions after type switching. The core lies in destroying old instances, deep copying configurations, and accurately rebuilding data structures by type.

A complete guide to using the keyboard to control the smooth movement of HTML elements A complete guide to using the keyboard to control the smooth movement of HTML elements Mar 13, 2026 pm 10:18 PM

This article explains in detail why transform: translate() combined with the keydown event cannot move elements, and provides a reliable solution based on CSS positioning and JavaScript, covering absolute positioning settings, coordinate update logic, code robustness optimization, and common pitfalls.

How to properly override default styles and implement custom CSS layouts in Divi theme builder How to properly override default styles and implement custom CSS layouts in Divi theme builder Mar 14, 2026 am 12:00 AM

This article explains in detail the root cause of style failure when applying custom CSS in the WordPress Divi theme builder. It provides practical solutions for improving selector specificity, accurately positioning elements, and rational use of !important, as well as debugging tips and code optimization examples.

How to dynamically pass HTML form data to analytics.track() method How to dynamically pass HTML form data to analytics.track() method Mar 13, 2026 pm 10:57 PM

This article explains in detail how to safely and efficiently extract user input from HTML forms and structure it into JavaScript objects as attribute parameters of analytics.track() to avoid hard coding and syntax errors and support flexible expansion.

How to optimize Lighthouse image scoring while maintaining high image quality How to optimize Lighthouse image scoring while maintaining high image quality Mar 11, 2026 pm 09:39 PM

This article explores why providing 2x images to high DPR devices may lower Lighthouse performance scores, and provides practical solutions to balance visual quality and real performance: including proper srcset configuration, image compression strategies, modern format selection, and load priority control.

Related articles