我正在使用Bootstrap和jQuery关键帧震动效果登录屏幕。后端由Flask处理。然而,我正面临一个问题,其中的错误信息"错误的用户名或密码。请再试一次。当用户名或密码输入错误时,登录框页脚不显示。
我尝试了各种方法,但都没有成功显示错误消息。有人能帮我解决这个问题吗?我在下面提供了.py和.html代码。
谢谢你的帮助。
Python Flask (main.py):from flask import Flask, redirect, render_template, g, request
import os
# Create a new Flask app
app = Flask(__name__, template_folder="web", static_folder="web")
app.config["TEMPLATES_AUTO_RELOAD"] = True
# Define a global version variable for cache busting
@app.before_request
def before_request():
g.version = os.environ.get("VERSION", "1.0.0")
# Define a route
@app.route("/")
def content():
# Render the login form template
return render_template("login.html")
@app.route("/login", methods=["GET", "POST"])
@app.route("/login", methods=["GET", "POST"])
def login():
error = None
if request.method == "POST":
# Check if the username and password are correct
username = request.form["username"]
password = request.form["password"]
if username == "admin" and password == "pass1":
# If the username and password are correct, redirect to the index page
return redirect("/index")
else:
# If the username and password are incorrect, show an error message
error = "Invalid username or password. Please try again."
# Render the login page with the error message (if any)
return render_template("login.html", error=error)
@app.route("/index")
def index():
return render_template("index.html")
# Run the Flask app
if __name__ == "__main__":
app.run(debug=True)
HTML (login.html):
<!DOCTYPE html>
<html lang="en-pl">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playground Window</title>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}?v={{ g.version }}">
<!-- Include Custom CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}?v={{ g.version }}">
<!-- Include jQuery -->
<script src="{{ url_for('static', filename='js/jquery-3.6.4.min.js') }}?v={{ g.version }}"></script>
<!-- Include Popper.js -->
<script src="{{ url_for('static', filename='js/popper.min.js') }}?v={{ g.version }}"></script>
<!-- Include Bootstrap JS -->
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}?v={{ g.version }}"></script>
<!-- Include jQuery Keyframes JS -->
<script src="{{ url_for('static', filename='js/jquery.keyframes.min.js') }}?v={{ g.version }}"></script>
</head>
<body>
<!-- Login Button -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#loginModal">
Login
</button>
<!-- Login Modal -->
<div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true"
aria-modal="true">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Body -->
<div class="modal-body">
<!-- Logo -->
<div class="logo">
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo" class="img-fluid"
data-bs-dismiss="modal" style="max-width: 200px;">
</div>
<form method="POST" action="/login">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password">
{% if error %}
<div id="login-error" class="text-danger">{{ error }}</div>
{% endif %}
</div>
</div>
<!-- Modal Footer -->
<div class="modal-footer">
{% if error %}
<div class="text-danger">{{ error }}</div>
{% endif %}
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
// Include jQuery Keyframes library
$.keyframe.define([{
name: 'shake',
'0%': { transform: 'translateX(0)' },
'10%': { transform: 'translateX(-20px)' },
'20%': { transform: 'translateX(20px)' },
'30%': { transform: 'translateX(-20px)' },
'40%': { transform: 'translateX(20px)' },
'50%': { transform: 'translateX(-20px)' },
'60%': { transform: 'translateX(20px)' },
'70%': { transform: 'translateX(-20px)' },
'80%': { transform: 'translateX(20px)' },
'90%': { transform: 'translateX(-20px)' },
'100%': { transform: 'translateX(0)' },
}]);
// Define the shaking effect
function shakeModal(errorMsg) {
$('#loginModal .modal-dialog').playKeyframe({
name: 'shake', // Name of the keyframe defined above
duration: '400ms', // Duration of the shake animation
timingFunction: 'linear', // Timing function for the shake animation
iterationCount: 1, // Number of times the animation should play
complete: function () { // Code to run after the animation completes
$('#login-error').text(errorMsg).show(); // Show the error message and set its text to the errorMsg parameter
}
});
}
// Hide the error message initially
$('#login-error').hide();
// Trigger the shaking effect when the wrong input is detected
$('form').submit(function (event) {
var username = $('#username').val();
var password = $('#password').val();
// Replace with your actual input validation logic
var inputIsValid = (username === 'admin' && password === 'pass1');
var errorMsg = '{{ error }}'; // Get the Flask error message from the template
if (!inputIsValid) {
shakeModal(errorMsg); // Pass the Flask error message to the shakeModal function
event.preventDefault(); // Prevent the form from being submitted
} else {
$('#login-error').hide(); // Hide the error message
}
});
});
</script>
</body>
</html>
亲爱的社区,
我正在使用Bootstrap和jQuery关键帧震动效果登录屏幕。后端由Flask处理。然而,我正面临一个问题,其中的错误信息"错误的用户名或密码。请再试一次。当用户名或密码输入错误时,登录框页脚不显示。
我尝试了各种方法,但都没有成功显示错误消息。有人能帮我解决这个问题吗?我在下面提供了.py和.html代码。
谢谢你的帮助。
Python Flask (main.py):from flask import Flask, redirect, render_template, g, request
import os
# Create a new Flask app
app = Flask(__name__, template_folder="web", static_folder="web")
app.config["TEMPLATES_AUTO_RELOAD"] = True
# Define a global version variable for cache busting
@app.before_request
def before_request():
g.version = os.environ.get("VERSION", "1.0.0")
# Define a route
@app.route("/")
def content():
# Render the login form template
return render_template("login.html")
@app.route("/login", methods=["GET", "POST"])
@app.route("/login", methods=["GET", "POST"])
def login():
error = None
if request.method == "POST":
# Check if the username and password are correct
username = request.form["username"]
password = request.form["password"]
if username == "admin" and password == "pass1":
# If the username and password are correct, redirect to the index page
return redirect("/index")
else:
# If the username and password are incorrect, show an error message
error = "Invalid username or password. Please try again."
# Render the login page with the error message (if any)
return render_template("login.html", error=error)
@app.route("/index")
def index():
return render_template("index.html")
# Run the Flask app
if __name__ == "__main__":
app.run(debug=True)
HTML (login.html):
<!DOCTYPE html>
<html lang="en-pl">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Playground Window</title>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}?v={{ g.version }}">
<!-- Include Custom CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}?v={{ g.version }}">
<!-- Include jQuery -->
<script src="{{ url_for('static', filename='js/jquery-3.6.4.min.js') }}?v={{ g.version }}"></script>
<!-- Include Popper.js -->
<script src="{{ url_for('static', filename='js/popper.min.js') }}?v={{ g.version }}"></script>
<!-- Include Bootstrap JS -->
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}?v={{ g.version }}"></script>
<!-- Include jQuery Keyframes JS -->
<script src="{{ url_for('static', filename='js/jquery.keyframes.min.js') }}?v={{ g.version }}"></script>
</head>
<body>
<!-- Login Button -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#loginModal">
Login
</button>
<!-- Login Modal -->
<div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true"
aria-modal="true">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Body -->
<div class="modal-body">
<!-- Logo -->
<div class="logo">
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo" class="img-fluid"
data-bs-dismiss="modal" style="max-width: 200px;">
</div>
<form method="POST" action="/login">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password">
{% if error %}
<div id="login-error" class="text-danger">{{ error }}</div>
{% endif %}
</div>
</div>
<!-- Modal Footer -->
<div class="modal-footer">
{% if error %}
<div class="text-danger">{{ error }}</div>
{% endif %}
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
// Include jQuery Keyframes library
$.keyframe.define([{
name: 'shake',
'0%': { transform: 'translateX(0)' },
'10%': { transform: 'translateX(-20px)' },
'20%': { transform: 'translateX(20px)' },
'30%': { transform: 'translateX(-20px)' },
'40%': { transform: 'translateX(20px)' },
'50%': { transform: 'translateX(-20px)' },
'60%': { transform: 'translateX(20px)' },
'70%': { transform: 'translateX(-20px)' },
'80%': { transform: 'translateX(20px)' },
'90%': { transform: 'translateX(-20px)' },
'100%': { transform: 'translateX(0)' },
}]);
// Define the shaking effect
function shakeModal(errorMsg) {
$('#loginModal .modal-dialog').playKeyframe({
name: 'shake', // Name of the keyframe defined above
duration: '400ms', // Duration of the shake animation
timingFunction: 'linear', // Timing function for the shake animation
iterationCount: 1, // Number of times the animation should play
complete: function () { // Code to run after the animation completes
$('#login-error').text(errorMsg).show(); // Show the error message and set its text to the errorMsg parameter
}
});
}
// Hide the error message initially
$('#login-error').hide();
// Trigger the shaking effect when the wrong input is detected
$('form').submit(function (event) {
var username = $('#username').val();
var password = $('#password').val();
// Replace with your actual input validation logic
var inputIsValid = (username === 'admin' && password === 'pass1');
var errorMsg = '{{ error }}'; // Get the Flask error message from the template
if (!inputIsValid) {
shakeModal(errorMsg); // Pass the Flask error message to the shakeModal function
event.preventDefault(); // Prevent the form from being submitted
} else {
$('#login-error').hide(); // Hide the error message
}
});
});
</script>
</body>
</html>
由于使用preventDefault()
抑制了表单数据的提交,因此页面不会重新加载,也不会出现错误消息,因为它没有创建。如果输入了错误的条目,则永远不会与服务器联系。
from datetime import timedelta
from flask import (
Flask,
jsonify,
redirect,
render_template,
request,
session,
url_for
)
from functools import wraps
app = Flask(__name__)
app.secret_key = 'your secret here'
def is_authenticated():
username = session.get('user')
return username and len(username.strip()) > 0
def login_required(f):
@wraps(f)
def wrapper(*args, **kwargs):
if not is_authenticated():
return redirect(url_for('login'))
return f(*args, **kwargs)
return wrapper
@app.before_request
def before_request():
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=1)
@app.route('/')
@login_required
def index():
return render_template('index.html')
@app.route('/login')
def login():
return render_template('login.html')
@app.post('/login')
def verify_login():
username = request.form.get('username')
password = request.form.get('password')
if username == 'admin' and password == 'pass':
session['user'] = username
return jsonify()
return jsonify(error='Invalid username or password. Pease try again.'), 422
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Login</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css"
integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ"
crossorigin="anonymous">
<style type="text/css">
html,
body {
height: 100%;
}
body {
display: flex;
align-items: center;
padding-top: 40px;
padding-bottom: 40px;
background-color: #f5f5f5;
}
.form-signin {
width: 100%;
max-width: 330px;
padding: 15px;
margin: auto;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="text"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.login-error {
font-size: 0.85em;
}
</style>
</head>
<body>
<main class="form-signin">
<form name="form-login">
<div class="form-floating">
<input type="text" name="username" id="username" class="form-control" />
<label for="username">Username</label>
</div>
<div class="form-floating">
<input type="password" name="password" id="password" class="form-control" />
<label for="password">Password</label>
</div>
<div class="login-error text-center text-danger mb-3"></div>
<button type="submit" class="w-100 btn btn-lg btn-primary">Login</button>
</form>
</main>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe"
crossorigin="anonymous"></script>
<script
src="https://code.jquery.com/jquery-3.6.4.min.js"
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8="
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquerykeyframes@1.0.8/dist/jquery.keyframes.min.js"></script>
<script type="text/javascript">
$(function() {
$.keyframe.define([{
name: 'shake',
'0%': { transform: 'translateX(0)' },
'10%': { transform: 'translateX(-8px)' },
'20%': { transform: 'translateX(8px)' },
'30%': { transform: 'translateX(-8px)' },
'40%': { transform: 'translateX(8px)' },
'50%': { transform: 'translateX(-8px)' },
'60%': { transform: 'translateX(8px)' },
'70%': { transform: 'translateX(-8px)' },
'80%': { transform: 'translateX(8px)' },
'90%': { transform: 'translateX(-8px)' },
'100%': { transform: 'translateX(0)' },
}]);
$('form[name="form-login"]').submit(function(event) {
event.preventDefault();
$.ajax({
method: 'POST',
url: {{ url_for('login') | tojson }},
data: $(this).serialize(),
cache: false,
statusCode: {
422: function(jqXHR){
$('.form-signin').playKeyframe({
name: 'shake',
duration: '400ms',
timingFunction: 'linear',
iterationCount: 1,
complete: function () {
$('.login-error').text(jqXHR.responseJSON.error);
}
});
}
}
}).done(function() {
window.location.replace({{ url_for('index') | tojson }});
});
});
});
</script>
</body>
</html>