项目介绍
项目架子:

完成添加后台用户功能
登录的功能 基于flask_script ,因为说后台管理用户,所以以命令的形式添加,不接受注册。巩固flask_script 在实际开发中的应用场景。
首先在models 中定义用户表:
字段定义有:姓名,邮箱,密码,签名,用户创建时间
1 #encoding:utf-8 2 from exts import db 3 from datetime import datetime 4 from werkzeug.security import generate_password_hash,check_password_hash 5 6 class User(db.Model): 7 __tablename__='user' 8 id=db.Column(db.Integer,primary_key=True,autoincrement=True) 9 name=db.Column(db.String(50),nullable=False) 10 email=db.Column(db.String(100),nullable=False,unique=True) 11 _passwd=db.Column(db.String(100),nullable=False) 12 # 签名 13 autograph=db.Column(db.String(50)) 14 join_time=db.Column(db.DateTime,default=datetime.now) 15 16 def __init__(self,n,e,p,a): 17 self.name=n 18 self.email=e 19 self.passwd=p 20 self.autograph=a 21 22 @property 23 def passwd(self): 24 return self._passwd 25 26 @passwd.setter 27 def passwd(self,raw_pwd): # 用户的密码利用 generate_password_hash函数 加密。 28 self._passwd=generate_password_hash(raw_pwd) 29 30 def check_passwd(self,pwd): # 用户密码检查,判断输入的密码是否正确 31 return check_password_hash(self.passwd,pwd)
定义了实体模型之后,我们需要把类隐射到数据库中,首先我们看程序主文件,PGpureLove.py
from flask import Flask from apps.home import home_bp from apps.admin import bp as admin_bp from exts import db,mail from flask_wtf import CSRFProtect import config def create_app(): # 定义工厂函数,创建app对象。 app = Flask(__name__) #Flaks方法 创建app对象 app.config.from_object(config) #绑定配置信息 app.register_blueprint(home_bp) #注册蓝图 前台 app.register_blueprint(admin_bp) #注册蓝图 后台 db.init_app(app) #让app 应用程序使用这个数据库设置 mail.init_app(app) #同上, 发送邮件时使用 CSRFProtect(app) return app if __name__ == '__main__': app=create_app() app.run()
app对象创建好之后,看下manage.py 文件:
#encoding:utf-8 from flask_script import Manager # 导入Manager 重要 必不可少。 from flask_migrate import Migrate,MigrateCommand # 做数据迁移用。 from PGpureLove import create_app #导入工厂函数 from exts import db #导入sqlalchemy 的实例对象 from apps.admin import models as admin_models #引入数据模型 AdminUser=admin_models.User #实例化 app=create_app() #创建一个app manager=Manager(app) #Manger绑定app Migrate(app,db) #绑定 app 与db manager.add_command('db',MigrateCommand) #MigrateCommand封装了一套数据迁移的命令 @manager.option('-n','--name',dest='name') @manager.option('-p','--passwd',dest='passwd') @manager.option('-e','--email',dest='email') @manager.option('-a','--autograph',dest='autograph') def create_Admin(name,passwd,email,autograph): u=AdminUser(name,email,passwd,autograph) db.session.add(u) db.session.commit() print("<用户已经创建>") if __name__=='__main__': manager.run()
在实际的开发环境中,经常会发生数据库修改的行为。一般我们修改数据库不会直接手动的去修改,而是去修改ORM对应的模型,然后再把模型映射到数据库中。
flask-migrate是基于Alembic进行的一个封装,并集成到Flask中,而所有的迁移操作其实都是Alembic做的,他能跟踪模型的变化,并将变化映射到数据库中。
1. 初始化一个环境:python manage.py db init
2. 自动检测模型,生成迁移脚本:python manage.py db migrate
3. 将迁移脚本映射到数据库中:python manage.py db upgrade
检查表,已经创建了:

4. 更多命令:python manage.py db --help
完成一三步之后,就可以使用 create_Admin 创建后台账号了。

查看数据库

完成前台的登录功能
后台登录功能:
涉及flask 框架知识点: flask_script ,flask_migrate,蓝图,g对象,session,宏,flask_wtf

首先设计前台登录页面,页面是网上找的:

首先定义一个宏。

登录界面:
{% from 'comm/_maro.html' import static %} // 导入宏
<!DOCTYPE html>
<div class="animate form login_form">
<section class="login_content">
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<h1>登录</h1>
<div>
<input name="username" type="text" class="form-control" placeholder="邮箱号" required="">
</div>
<div>
<input name="password" type="password" class="form-control" placeholder="密码" required="">
{% if message %}
<p style="text-align: center" class="text-danger">{{ message }}</p>
{% endif %}
</div>
<div class="checkbox3 checkbox-success checkbox-inline checkbox-check checkbox-round checkbox-light">
<input name="remember" value="1" type="checkbox" id="checkbox-fa-light-1" checked="">
<label for="checkbox-fa-light-1">
记住密码
</label>
</div>
<div>
<button class="btn btn-default submit" type="submit">登录</button>
<a class="reset_pass" href="#">您的密码丢失?</a>
</div>
<div class="clearfix"></div>
<div class="separator">
<p class="change_link">第一次访问网站?
<a href="http://demo.cssmoban.com/cssthemes4/cttp_1_gentelella/production/login.html#signup" class="to_register"> 注册账户 </a>
</p>
<div class="clearfix">
</div>
<br>
<div>
<p>©2016 All Rights Reserved. Gentelella Alela! is a Bootstrap 3 template. Privacy and Terms</p>
</div>
</div>
</form>
</section>
</div>
这时候 需要创建 form.py 创建
from wtforms import Form class BaseForm(Form): def get_error(self): return self.errors.items()[1][0]
from apps.forms import BaseForm from wtforms import StringField,IntegerField,PasswordField from wtforms.validators import Required,Email,EqualTo,Length,InputRequired from flask import g from utils import cacheLib class LoginForm(BaseForm): username=StringField(validators=[Email(message='邮箱格式不正确'),InputRequired(message='请输入邮箱')]) password=StringField(validators=[InputRequired(message='请输入密码'),Length(6,50,message='密码长度只能6-50')]) remember=IntegerField()
完成之后 ,我们需要定义个一视图来渲染login.html 页面,进入views.py 中。
from flask import Blueprint,render_template,request,g,session,redirect,url_for
from .forms import LoginForm,RestPwdForm
from flask import views,render_template
from .models import User
from .decorators import login_requid
import config
from exts import db
bp=Blueprint('admin',__name__,url_prefix='/admin')
# 登录功能 基于调度方法的视图 class LoginView(views.MethodView): #需要继承 MethodView方法 def get(self,message=None): #get 请求登录页面 return render_template('comm/login.html',message=message) def post(self): #处理用户提交的登录信息 form=LoginForm(request.form) # 处理表单提交的数据 传递 request.form if form.validate(): # 如果验证通过。 name=form.username.data #获取用户名 pwd=form.password.data #获取密码 remb=form.remember.data #获取记住密码 user=User.query.filter_by(email=name).first() #通过flask_sqlalchemy 查询该用户。 if user and user.check_passwd(pwd) : #检查输入的密码对不对,内部调用的check_password_hash方法,如果有这个用户 并且密码对的 session[config.CMS_USER_ID]=user.id # 首先把用户di传到seesion中 if remb: session.permanent=True return redirect(url_for('admin.index')) else: return self.get(message='密码错误') else: return "验证不通过" bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))
登录功能完成, 我们需要测试几种场景:
表单验证的信息

1 密码输入正确的时候,登录正常

2 直接点登录:
用户名 密码都会有提示,

但是这只说前端的验证,后台我们同样是要去处理这种异常情况。
3 用户名或密码输入错误
建议不要提示太明显,以前做测试的时候要求开发提示清晰,让用户知道自己说用户名或者密码输错了。
但这样也不安全。活跃的用户是不可能把账号都忘掉的。

因为没有使用ajax ,http是无状态的,当输入错误的邮箱或者密码,我们想在表单中保留上次输入的数据,这就需要在把数据回传到render_templete 函数中。
4 登录成功,正常跳转到首页。

5 当用户在登录之后,我们需要验证session。

这些页面都说要登录之后才能看到的。所以我们现在要来实现这个装饰器。
from flask import session,redirect,url_for from functools import wraps # 避免在使用的过程 from config import CMS_USER_ID def login_requid(func): @wraps(func) def warp(*args,**kwargs): if CMS_USER_ID in session: return func(*args,**kwargs) else: return redirect(url_for('admin.login')) return warp
之后 只要在需要的地方引入即可。
