flask 项目结构,完成一个注册,登陆功能。


项目介绍

项目架子:

  

 

 

完成添加后台用户功能

登录的功能 基于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

之后 只要在需要的地方引入即可。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM