from datetime import datetime
from app import db
# 会员
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True) # 编号
name = db.Column(db.String(100), unique=True) # 昵称
pwd = db.Column(db.String(100)) # 密码
email = db.Column(db.String(100), unique=True) # 邮箱
phone = db.Column(db.String(11), unique=True) # 手机号码
info = db.Column(db.Text) # 个性简介
face = db.Column(db.String(255), unique=True) # 头像
addtime = db.Column(db.DateTime, index=True, default=datetime.now) # 注册时间
uuid = db.Column(db.String(255), unique=True) # 唯一标志符
userlogs = db.relationship('Userlog', backref='user') # 会员日志外键关系关联
comments = db.relationship('Comment', backref='user') # 评论外键关系关联
moviecols = db.relationship('Moviecol', backref='user') # 收藏外键关系关联
def __repr__(self):
return "<User %r>" % self.name
# 检查密码匹配
def check_pwd(self, pwd):
from werkzeug.security import check_password_hash
return check_password_hash(self.pwd, pwd)
# 会员登录日志
class Userlog(db.Model):
__tablename__ = "userlog"
id = db.Column(db.Integer, primary_key=True) # 编号
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 所属会员
ip = db.Column(db.String(100)) # 登录IP
addtime = db.Column(db.DateTime, index=True, default=datetime.now) # 登录时间
def __repr__(self):
return "<Userlog %r>" % self.id
class LoginForm(FlaskForm):
name = StringField(
label="昵称(账号)",
description="昵称(账号)",
validators=[
DataRequired("请输入昵称(账号)"),
],
render_kw={
"class": "form-control input-lg",
"placeholder": "昵称(账号)",
}
)
pwd = PasswordField(
label="密码",
description="密码",
validators=[
DataRequired("请输入密码"),
],
render_kw={
"class": "form-control input-lg",
"placeholder": "密码",
}
)
submit = SubmitField(
label="登录",
render_kw={
"class": "btn btn-lg btn-success btn-block",
}
)
# 最好在forms中验证账号
def validate_name(self, field):
name = field.data
if User.query.filter_by(name=name).count() == 0:
raise ValidationError("账号不存在")
{% for msg in get_flashed_messages(category_filter=["fail"]) %}
<div><span style="color: red">{{ msg }}</span></div>
{% endfor %}
<div class="panel-body">
<form role="form" method="post" action="{{ url_for('home.login') }}">
<fieldset>
<div class="form-group">
<label for="input_contact"><span class="glyphicon glyphicon-user"></span> {{ form.name.label }}</label>
{{ form.name }}
</div>
{% for err in form.name.errors %}
<div class="col-md-12" id="error_contact">{{ err }}</div>
{% endfor %}
<div class="form-group">
<label for="input_password"><span class="glyphicon glyphicon-lock"></span> {{ form.pwd.label }}</label>
{{ form.pwd }}
</div>
{% for err in form.pwd.errors %}
<div class="col-md-12" id="error_contact">{{ err }}</div>
{% endfor %}
{{ form.submit }}
{{ form.csrf_token }}
</fieldset>
</form>
第三步: views中逻辑编写
from . import home
from flask import render_template, redirect, url_for, flash, session, request
from .forms import RegistForm, LoginForm
from werkzeug.security import generate_password_hash
from app.models import User, Userlog
from app import db
import uuid
from functools import wraps
# 权限装饰器
def user_login_req(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if "user" not in session:
return redirect(url_for('home.login', next=request.url))
return f(*args, **kwargs)
return decorated_function
@home.route("/login/", methods=["GET", "POST"])
def login():
form = LoginForm()
if form.validate_on_submit():
data = form.data
user = User.query.filter_by(name=data.get("name")).first()
if not user.check_pwd(data.get("pwd")):
flash("密码错误", "fail")
return redirect(url_for('home.login'))
session['user'] = user.name
session['user_id'] = user.id
user_log = Userlog(
user_id=user.id,
ip=request.remote_addr,
)
db.session.add(user_log)
db.session.commit()
return redirect(url_for('home.user'))
return render_template("home/login.html", form=form)
@home.route("/logout/")
def logout():
session.pop("user", None)
session.pop("user_id", None)
return redirect(url_for('home.login'))