Flask+Bootstrap实战三

书接上回,完成了用户注册的页面,下面来完成用户登录的页面

2025-03-07 21:20:34 星期五

项目教程地址:

Youtobe源地址:Bootstrap Flask
Bilibili搬运:哔哩哔哩


一.Flask制作用户登录界面

flask-login教程文档

  1. 首先需要在app.py中修改导入from flask_login import LoginManager,之后login = LoginManager(app)

  2. 修改model.py用户模型。加入了一个user_loader回调


from flask_login import UserMixin

from app import db, login


@login.user_loader
def load_user(id):
	return User.query.get(id)

class User(db.Model, UserMixin):
	id = db.Column(db.Integer, primary_key=True)
	username = db.Column(db.String(20), unique=True)
	email = db.Column(db.String(120), unique=True)
	password = db.Column(db.String(20), unique=True)

	def __repr__(self):
		return '<User %r>' % self.username
  1. 在routes.py中新建一个login路由函数

@app.route('/login', methods=['GET', 'POST'])
def login():
	form = LoginForm()
	if form.validate_on_submit():
		pass
	return render_template("login.html", form=form)
  1. 在用户注册表单中form.py中编写LoginForm类,注意这里需要先从wtforms中导入BooleanField

class LoginForm(FlaskForm):
	username = StringField("Username", validators=[DataRequired(), Length(min=3, max=20)])
	password = PasswordField("Password", validators=[DataRequired(), Length(min=6, max=20)])
	remember = BooleanField("Remember")
	submit = SubmitField("Login")
  1. 新建login.html模板

{% extends "base.html" %}

{% block app_content %}
 <h1>Login Now</h1>
 <br>
 <div class="row">
  <div class="col-md-6">
   {% import 'bootstrap/wtf.html' as wtf %}
   {{ wtf.quick_form(form) }}
  </div>
 </div>
{% endblock %}
  1. 在navbar.html中新建一login标签

最后运行截图如下

二.用户名和密码校验以及登录成功界面

  1. 修改routes.py文件,首先判断当前用户是不是第一次出现,另外,检查当前输入的密码是否与user查询得到的密码相匹配,如果匹配,fflash消息后重定向到successful界面,如果不匹配,则同样flash一条消息。

@app.route('/login', methods=['GET', 'POST'])
def login():
	form = LoginForm()
	if form.validate_on_submit():
		username = form.username.data
		password = form.password.data  # Use the plain password from the form
		remember = form.remember.data
		user = User.query.filter_by(username=username).first()
		if user and bcrypt.check_password_hash(user.password, password):
			# user exists and password is true
			login_user(user, remember=remember)
			flash("Login success", category="info")
			return redirect(url_for("login_success"))
		else:
			flash("user not exists or password not true", category="danger")
	return render_template("login.html", form=form)

这里其实有一个小问题,就是如果登录不成功,他并不会flash一条消息,就是没动静


函数的category参数用于指定消息的类别,通常用于设置消息的样式。常见的类别包括:

  • success:表示成功消息,通常显示为绿色。
  • info:表示信息消息,通常显示为蓝色。
  • warning:表示警告消息,通常显示为黄色。
  • danger:表示错误消息,通常显示为红色。

所以在这里,除了给原先的login_success做登录成功的页面跳转之外,还需要在login.html中加上falshing处理消息,并给danger,代码如下

点击查看代码
{% extends "base.html" %}

{% block app_content %}
  <h1>Login Now</h1>
  <br>
    <div class="row">
      <div class="col-md-6">
        {% with messages = get_flashed_messages(with_categories=True) %}
          {% if messages %}
            {% for category, message in messages %}
              <div class="alert alert-{{ category }}">
                {{ message }}
              </div>
            {% endfor %}
          {% endif %}
        {% endwith %}
        {% import 'bootstrap/wtf.html' as wtf %}
        {{ wtf.quick_form(form) }}
      </div>
    </div>
    
{% endblock %}
  1. 在routes.py中添加新的路由

@app.route('/login_success')
def login_success():
	return render_template("login_success.html")
  1. 制作login_successful模板,这个和register.html模板一摸一样
点击查看代码
{% extends "bootstrap/base.html" %}


{% block content %}
  <div class = "container">
    <div class="row">
      <div class="col-md-6">
        {% with messages = get_flashed_messages(with_categories=True) %}
          {% if messages %}
            {% for category, message in messages %}
              <div class="alert alert-{{ category }}">
                {{ message }}
              </div>
            {% endfor %}
          {% endif %}
        {% endwith %}
      </div>
    </div>
  </div>

  <script>
    // Wait for 2 seconds and then redirect to the index page
    setTimeout(function() {
        window.location.href = "{{ url_for('index') }}";
    }, 2000);
  </script>
{% endblock %}

这样就可以实现密码不对或者用户名错误时有红色警告了

  1. 此时就可以进行登录了,但是这样就是可以重复进行登录,所以需要进行判断当前用户不让他重复登录。修改login的路由,同时修改register的路由

@app.route('/login', methods=['GET', 'POST'])
def login():
	if current_user.is_authenticated:
		return redirect(url_for("index"))
  1. 为了确保用户必须登录之后才能进入index页面,需要在__init__.py初始化时加上。其目的就是当用户处于未登录状态时,会在login页面提示"You must login to access this page"

login.login_view = "login"
login.login_message = "You must login to access this page"
login.login_message_category = "info"
  1. 最后就是为了在登录状态只显示登出按钮,在未登录状态只显示登录按钮,需要在navbar.html文件中做如下修改,三个<li>标签中间加if判断即可标签中间加if判断即可

<ul class="nav navbar-nav navbar-right">
  {% if not current_user.is_authenticated %}
  <li class="{% if request.endpoint == 'login' %}active{% endif %}">
	<a href="{{url_for('login')}}">Login</a>
  </li>
  <li class="{% if request.endpoint == 'register' %}active{% endif %}">
	<a href="{{url_for('register')}}">Register</a>
  </li>
  {% else %}
  <li class="{% if request.endpoint == 'logout' %}active{% endif %}">
	<a href="{{url_for('logout')}}">Logout</a>
  </li>
  {% endif %}
</ul>

三.添加重置密码的界面

  1. 首先在用户登录界面login.html做修改如下,在最下方添加如下代码,和上面的隔开

<div class="row">
  <div class="col-md-6">
    <hr>
    Forget your password?
    <a href= "{{ url_for('send_password_reset_request') }}">
      Please click here to reset your password.
    </a>
  </div>
</div>
  1. 之后新建路由函数,此时可以发现我们缺少一个form,所以下一步需要在forms.py中新建一个PasswordResetForm

@app.route('/send_password_reset_request', methods=['GET', 'POST'])
def send_password_reset_request():
	form = PasswordResetForm()
	return render_template("send_password_reset_request.html", form=form)
  1. 新建一个PasswordResetForm

class PasswordResetForm(FlaskForm):
	email = StringField("Email", validators=[DataRequired(), Email()])
	submit = SubmitField("send")

	def validate_email(self, email):
		user = User.query.filter_by(email=email.data).first()
		if not user:
			raise ValidationError("email not exists")
  1. 新建一个send_password_reset_request.html,和register.html模板文件几乎一模一样,现在发现了就是form中定义了几个Field,那么他在html模板中进行渲染的时候就会自动生成几个,很方便

{% extends "base.html" %}

{% block app_content %}
 <h1>Reset Now</h1>
 <br>
 <div class="row">
  <div class="col-md-6">
   {% import 'bootstrap/wtf.html' as wtf %}
   {{ wtf.quick_form(form) }}
  </div>
 </div>
{% endblock %}

ok,这个也做完了


  1. 优化一些页面跳转。

    1. 首先第一个就是logout的时候,加一个@login_required,来确保只有在登录状态下才能登出,但是这个并不是必要的,因为在未登录状态前面设置了navbar并不会显示logout按钮

    2. 在register_success.html编写跳转的时候,不再去index页面,而是直接去login页面

posted on 2025-03-07 21:19  bnbncch  阅读(57)  评论(0)    收藏  举报