Home > Blockchain >  Login modal content from another page with flask wtf on top of Bootstrap, how to get form answer?
Login modal content from another page with flask wtf on top of Bootstrap, how to get form answer?

Time:04-28

I'm new to HTML programming so I'll try to describe my problem the best I can. This is adapted from Miguel Grinberg's Flask tutorial, using Boostrap 4.6, through quite a good amount of research. My pages are extended from a base template. My base contain a link to a login modal page, which is getting its content from a separate HTML file. I'm using Flask WTF for this login modal page. When I go to login and click on the "Sign Up" button, seems like it reloads the page I am. I think its sending the form.submit answer to that page's route (in VS Code's terminal, it says there is a POST to /index for example), so the question is how can I get the 'Sign In' button answer to the login route? I've found answers to something alike this question, but not similar enough to implement them.

(Relevant) routes.py:

from app import app, db
from app.models import User, Notification, Rule
from flask import render_template, flash, redirect, url_for, request, g, jsonify
from flask_login import current_user, login_user, logout_user, login_required
from app.forms import LoginForm, RegistrationForm, RuleForm

@app.route('/')
@app.route('/index', methods=['GET', 'POST'])
def index():
    if not current_user.is_authenticated:
        current_user.username="Guest User"
    return render_template('index.html', title='Home')

@app.route('/login', methods=['GET', 'POST'])
def login_modal():
    print("login_modal init")
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        print("validate form")
        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid username or password!', 'warning')
            return redirect(url_for('login'))
        login_user(user, remember=form.remember_me.data)
        flash('Successfull login!', 'success')
        return redirect(url_for('index'))
    return render_template('login-modal.html', title='Sign In', form=form)

This is my base:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">

    <!-- Custom fonts for this template-->
    <link href="{{ url_for('static', filename='fontawesome-free/css/all.min.css') }}" rel="stylesheet" type="text/css"> 
    <link
        href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i"
        rel="stylesheet">

    <!-- Custom styles for this template-->
    <link href="{{ url_for('static', filename='css/notificationservice.min.css') }}" rel="stylesheet">
    
    <link href="{{ url_for('static', filename='css/dataTables.bootstrap4.min.css') }}" rel="stylesheet">
    
    <link href="https://cdn.jsdelivr.net/gh/Eonasdan/tempus-dominus@master/dist/css/tempus-dominus.css"
    rel="stylesheet" crossorigin="anonymous">
    
    <!-- Bootstrap core JavaScript-->
    <script src="{{ url_for('static', filename='js/jquery/jquery.min.js') }}"></script> 
    <script src="{{ url_for('static', filename='bootstrap-v4.6.0-dist/js/bootstrap.bundle.min.js') }}"></script> 
    <script src="{{ url_for('static', filename='bootstrap-v4.6.0-dist/js/bootstrap.min.js') }}"></script> 

    <!-- Core plugin JavaScript-->
    <script src="{{ url_for('static', filename='js/jquery-easing/jquery.easing.min.js') }}"></script> 

    <!-- Custom scripts for all pages-->
    <script src="{{ url_for('static', filename='js/notificationservice.min.js') }}"></script> 

    <!-- Page level plugins -->
    <script src="{{ url_for('static', filename='js/jquery/jquery.dataTables.min.js') }}"></script> 
    <script src="{{ url_for('static', filename='js/dataTables.bootstrap4.min.js') }}"></script> 

    <!-- Page level custom scripts -->
    <script src="{{ url_for('static', filename='js/datatables-demo.js') }}"></script>
    
    
    <!-- Favicon -->
    <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='smartphone.ico') }}"> 
    
    <title>Notification Service - {{title}}</title>

</head>

<body id="page-top">        
    <!-- Page Wrapper -->
    <div id="wrapper">

        <!-- Sidebar -->
        <ul  id="accordionSidebar">

            <!-- Sidebar - Brand -->
            <a  href="{{url_for('index')}}">
                <div >
                    <i ></i>
                </div>
                <div >Notification Service</div>
            </a>

            <!-- Divider -->
            <hr >
            <!-- Nav Item - Notifications -->
            <li >
                <a  href="{{url_for('notifications')}}">
                    <i ></i>
                    <span >Notifications</span></a>
                <p></p>
            </li>

            <!-- Divider -->
            <hr >
            <!-- Nav Item - Rules -->
            <li >
                <a  href="{{url_for('rules')}}">
                    <i ></i>
                    <span>Rules</span></a>
                <p></p>
            </li>

            {%if current_user.username == 'admin' %}
            <!-- Divider -->
            <hr >
            <!-- Nav Item - Manage Accounts -->
            <li >
                <a  href="{{url_for('accounts')}}">
                    <i ></i>
                    <span>Manage Accounts</span></a>
                <p></p>
            </li>
              <!-- Divider -->
              <hr >
              <!-- Nav Item - Manage Accounts -->
              <li >
                  <a  href="{{url_for('rules_configure')}}">
                      <i ></i>
                      <span>Configure Rules</span></a>
                  <p></p>
              </li>
            {% endif %}
            
            <!-- Divider -->
            <hr >
            <!-- Sidebar Toggler (Sidebar) -->
            <div >
                <button  id="sidebarToggle"></button>
            </div>

        </ul>
        <!-- End of Sidebar -->

        <!-- Content Wrapper -->
        <div id="content-wrapper" >

            <!-- Main Content -->
            <div id="content">

                <!-- Topbar -->
                <nav >
                    <div  style="display:flex;justify-content:center;">
                        <div  style="display:inline;text-align:center;width:auto;">
                            {% with messages = get_flashed_messages(with_categories=true) %}
                                {% if messages %}
                                {% for category, message in messages %}
                                    {% if category == 'message' %}
                                        <div  id="alert" role="alert" 
                                            style="margin-bottom: 0rem;">
                                    {% else %}
                                        <div  id="alert" role="alert" 
                                            style="margin-bottom: 0rem;">
                                    {% endif %}
                                        {{ message }}
                                    </div>
                                {% endfor %}
                                {% endif %}
                            {% endwith %}
                        </div>
                    </div>
                    <!-- Sidebar Toggle (Topbar) -->
                    <button id="sidebarToggleTop" >
                        <i ></i>
                    </button>


                    <!-- Topbar Navbar -->
                    <ul >
                        <div ></div>

                        <!-- Nav Item - User Information -->
                        <li >
                            <a  id="userDropdown" role="button"
                                data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                                <span >{% if current_user.is_authenticated %}
                                    {{current_user.username}}{%else%}Guest User{% endif %}</span>
                                <div >
                                    {% if current_user.is_authenticated %}
                                        <i ></i>
                                    {%else%}
                                        <i ></i>
                                    {% endif %}
                                    
                                    <!--<i ></i>-->
                                </div>
                            </a>
                            {% if current_user.is_authenticated %}
                            <!-- Dropdown - User Information -->
                            <div 
                                aria-labelledby="userDropdown">
                                <a  href="{{url_for('profile', username=current_user.username)}}">
                                    <i ></i>
                                    Profile
                                </a>
                                <div ></div>
                                <a  href="{{url_for('logout')}}" data-toggle="modal" data-target="#logoutModal">
                                    <i ></i>
                                    Logout
                                </a>
                            </div>
                            {% else %}
                            <div 
                                aria-labelledby="userDropdown">
                                <a  href="{{url_for('login_modal')}}" data-toggle="modal" 
                                    data-target="#loginModal">
                                    <i ></i>
                                    Login
                                </a>
                                <div ></div>
                                <a  href="{{url_for('register')}}">
                                    <i ></i>
                                    Register
                                </a>
                            </div>
                            {%endif%}
                        </li>

                    </ul>

                </nav>
                <!-- End of Topbar -->

                <!-- Begin Page Content -->
                <div >
                    {% block app_content %}
                    {% endblock %}
                </div>
                
            </div>
            <!-- End of Main Content -->

            <!-- Footer -->
            <footer >
                <div >
                    <div >
                        <span>NS 2022 &copy;</span>
                    </div>
                </div>
            </footer>
            <!-- End of Footer -->

        </div>
        <!-- End of Content Wrapper -->

    </div>
    <!-- End of Page Wrapper -->

    <!-- Scroll to Top Button-->
    <a  href="#page-top">
        <i ></i>
    </a>   
    <!-- Login Modal-->
    <div  id="loginModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
        aria-hidden="true">
        <div  role="document">
            <div >
            </div>
        </div>
    </div>
    <!-- Logout Modal-->
    <div  id="logoutModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
        aria-hidden="true">
        <div  role="document">
            <div >
                <div >
                    <h5  id="exampleModalLabel">Ready to Leave?</h5>
                    <button  type="button" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">×</span>
                    </button>
                </div>
                <div >Select "Logout" below if you are ready to end your current session.</div>
                <div >
                    <button  type="button" data-dismiss="modal">Cancel</button>
                    <a  href="{{url_for('logout')}}">Logout</a>
                </div>
            </div>
        </div>
    </div>

    <script>
        $('body').on('click', '[data-target="#loginModal"]', function(){
            $($(this).data("target") ' .modal-content').load($(this).attr('href'));
        }); 
    </script>

    <script type="text/javascript">
        $(document).ready(function() {
        setTimeout(function() {
            $('#alert').fadeOut('slow');
        }, 3000); // <-- time in milliseconds
        });
    </script>

    <script type="text/javascript">
        $(document).ready(function() {
            $("#sidebarToggle").click(function(e) {
                e.preventDefault();
                $("#accordionSidebar").toggleClass("toggled");
                $('#accordionSidebar.toggled').find("#sidebar").find(".collapse").collapse('hide');
            });
        });
    </script>

    </body>

</html>

This is my index.html:

{% extends 'base.html' %}
{% set active_page = "index" %}

{% block app_content %}
    <h1 >Some content...</h1>
{% endblock %}

The login page:

<div >
    <!-- Nested Row within Card Body -->
    <div >
        <div >
            <div >
                <div >
                    <h1 >Login</h1>
                </div>
                <form  action="" method="post" id="loginForm" novalidate>
                    <div >
                        <div>
                        {{ form.username(   
                            (" is-invalid" if form.username.errors else ""), placeholder="Username", 
                            id="inputValUsername", size=32, **{"aria-describedby": "inputValUsername", 
                            "required": ""}) }}
                        </div>
                        {% for error in form.username.errors %}
                        <div >
                            <small>{{ error }}</small>
                        </div>
                        {% endfor %}
                    </div>
                    <div >
                        <div>
                        {{ form.password(   
                            (" is-invalid" if form.password.errors else ""), placeholder="Password", 
                            id="inputValPassword", size=32, **{"aria-describedby": "inputValPassword", 
                            "required": ""}) }}
                        </div>
                        {% for error in form.password.errors %}
                        <div >
                            <small>{{ error }}</small>
                        </div>
                        {% endfor %}
                    </div>
                    <div >
                        <div >
                            {{ form.remember_me() }} {{ form.remember_me.label }}
                        </div>
                    </div>
                    {{ form.submit(, id='form-submit') }}
                </form>
                <hr>
                <div >
                    <a  href="{{url_for('forgot')}}">Forgot Password?</a>
                </div>
                <div >
                    <a  href="{{url_for('register')}}">Create an Account!</a>
                </div>
                <div >
                    <a  href="{{url_for('index')}}">Back to Notification Service Home</a>
                </div>
            </div>
        </div>
    </div>
</div>

CodePudding user response:

In your form html element change action="" to action="/login"

  • Related