python之Flask实现简单登录功能的示例代码


Posted in Python onDecember 24, 2018

网站少不了要和数据库打交道,归根到底都是一些增删改查操作,这里做一个简单的用户登录功能来学习一下Flask如何操作MySQL。

用到的一些知识点:Flask-SQLAlchemy、Flask-Login、Flask-WTF、PyMySQL

这里通过一个完整的登录实例来介绍,程序已经成功运行,在未登录时拦截了success.html页面跳转到登录页面,登录成功后才能访问success。

以下是项目的整体结构图:

python之Flask实现简单登录功能的示例代码

首先是配置信息,配置了数据库连接等基本的信息,config.py

DEBUG = True 
SQLALCHEMY_ECHO = False 
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:1011@localhost/rl_project?charset=utf8' 
SECRET_KEY = '*\xff\x93\xc8w\x13\x0e@3\xd6\x82\x0f\x84\x18\xe7\xd9\\|\x04e\xb9(\xfd\xc3'

common/_init_.py

# config=utf-8 
from flask_sqlalchemy import SQLAlchemy 

__all__ = ['db'] 

db = SQLAlchemy()

数据库配置类,common/data.py

# config=utf-8 

from sqlalchemy import create_engine 

from sqlalchemy.sql import text 

from config import SQLALCHEMY_DATABASE_URI, SQLALCHEMY_ECHO 

  

  

def db_query(sql, settings=None, echo=None): 

  

  if settings is None: 

    settings = SQLALCHEMY_DATABASE_URI 

  

  if echo is None: 

    echo = SQLALCHEMY_ECHO 

  

  return create_engine(settings, echo=echo).connect().execute(text(sql)).fetchall() 

  

  

def db_execute(sql, settings=None, echo=None): 

  

  if settings is None: 

    settings = SQLALCHEMY_DATABASE_URI 

  

  if echo is None: 

    echo = SQLALCHEMY_ECHO 

  

  return create_engine(settings, echo=echo).connect().execute(text(sql)).rowcount

SQLALCHEMY_DATABASE_URI用于连接数据的数据库。

SQLALCHEMY_ECHO如果设置成 True,SQLAlchemy 将会记录所有 发到标准输出(stderr)的语句,这对调试很有帮助。
当然,我们在setting中设置了基本的连接数据库信息,启动时加载app = create_app('../config.py'),所以这个类删掉也不会报错。

form/login_form.py

# config=utf-8 

from flask_wtf import FlaskForm as Form 

from wtforms import StringField, PasswordField 

from wtforms.validators import DataRequired 

  

  

class LoginForm(Form): 

  accountNumber = StringField('accountNumber', validators=[DataRequired('accountNumber is null')]) 

  password = PasswordField('password', validators=[DataRequired('password is null')])

使用Flask-WTF做登录的表单验证,这里简单做了账号密码不为空如,当我们不填写密码时,点击登录:

python之Flask实现简单登录功能的示例代码

model/_init_.py

# config=utf-8 
from flask import Flask 
from flask_login import LoginManager 
from common import db 
login_manager = LoginManager() 

login_manager.login_view = "user.login" 

def create_app(config_filename=None): 

  app = Flask(__name__) 

  login_manager.init_app(app) 
  if config_filename is not None: 

    app.config.from_pyfile(config_filename) 

    configure_database(app) 
  return app 

def configure_database(app): 
  db.init_app(app)

其中,login_manager.login_view = "user.login" 指定了未登录时跳转的页面,即被拦截后统一跳到user/login这个路由下model/user_model.py

# config=utf-8 

from flask_login import UserMixin 
from common import db 
class User(db.Model, UserMixin): 

  user_id = db.Column('id', db.Integer, primary_key=True) 

  accountNumber = db.Column(db.String(200), unique=True) 

  password = db.Column(db.String(50), unique=True) 

  name = db.Column(db.String(20), unique=True) 

  __tablename__ = 'tb_user' 

  def __init__(self, user_id=None, account_number=None, password=None, name="anonymous"): 
   self.user_id = user_id 

    self.accountNumber = account_number 

    self.password = password 

    self.name = name 
  def is_authenticated(self): 

    return True 
  def is_active(self): 

    return True 

  def is_anonymous(self): 

    return False 

  def get_id(self): 

    return unicode(self.user_id) 

  def __repr__(self): 

    return '<User %r>' % (self.accountNumber)

这里需要注意:

def get_id(self): 
return unicode(self.user_id)

该方法不可缺少,否则会报:NotImplementedError: No `id` attribute - override `get_id`错误。

get_id()

返回一个能唯一识别用户的,并能用于从 user_loader 回调中 加载用户的 unicode 。注意着 必须 是一个 unicode ——如果 ID 原本是 一个 int 或其它类型,你需要把它转换为 unicode 。

is_authenticated()

当用户通过验证时,也即提供有效证明时返回 True

is_active()

如果这是一个通过验证、已激活、未被停用的账户返回 True 。

is_anonymous()

如果是一个匿名用户,返回 True 。

login.py

#encoding:utf-8 

#!/usr/bin/env python 

from flask import render_template, request, redirect, Flask, Blueprint 

from flask_login import login_user, login_required 

from model.user_model import User 

from model import login_manager 

from form.login_form import LoginForm 

  

  

userRoute = Blueprint('user', __name__, url_prefix='/user', template_folder='templates', static_folder='static') 

 

@login_manager.user_loader 

def load_user(user_id): 

  return User.query.get(int(user_id)) 

 

 

@userRoute.before_request 

def before_request(): 

  pass 

 

@userRoute.route('/success') 

@login_required 

def index(): 

  return render_template('success.html') 

 

@userRoute.route('/login', methods=['GET', 'POST']) 

def login(): 

  form = LoginForm() 

  if request.method == 'POST': 

    if not form.validate_on_submit(): 

      print form.errors 

      return render_template('login.html', form=form) 

  

    user = User.query.filter(User.accountNumber == form.accountNumber.data, 

                 User.password == form.password.data).first() 

    if user: 

      login_user(user) 

      return render_template('success.html') 

  

  return render_template('login.html', form=form)

其中,要实现一个load_user()回调方法,这个回调用于从会话中存储的用户 ID 重新加载用户对象,id存在则返回对应的用户对象,不存在则返回none。

有些操作是需要用户登录的,有些操作则无需用户登录,这里使用到了@login_required,在每一个需要登录才能访问的路由方法上加@login_required即可。

启动类,runserver.py

# config=utf-8 

from login import userRoute 

from model import create_app 

DEFAULT_MODULES = [userRoute] 

app = create_app('../config.py') 

for module in DEFAULT_MODULES: 

  app.register_blueprint(module) 


@app.before_request 

def before_request(): 

  pass  

if __name__ == '__main__': 

  app.run(debug=True)

DEFAULT_MODULES = [userRoute]是将userRoute蓝图注册入app,才能启动login中的userRoute路由,我们在login.py中使用了蓝图:userRoute = Blueprint('user', __name__, url_prefix='/user', template_folder='templates', static_folder='static')

@app.before_request 

def before_request(): 

  pass

这是一个全局的方法,在请求开始之前被调用,在某些场景下做一些提示或者特殊处理,当然这里没用上,直接pass,这个方法去掉对项目没有影响。基本样式模版,base.html

<!DOCTYPE html> 

<html lang="cn"> 

<head> 

  <meta charset="UTF-8"> 

  <title>{% block title %}{% endblock %}</title> 

  <script src="{{ url_for('static', filename='jquery1.42.min.js') }}"></script> 

  {% block head %}{% endblock %} 

</head> 

<body> 

{% block content %}{% endblock %} 

</body> 

</html>

登录前台页面,login.html

{% extends "base.html" %} 

{% block title %}python flask user page{% endblock %} 

{% block head %} 

  <style type="text/css"></style> 

{% endblock %} 

{% block content %} 

  <form action="{{ url_for('user.login') }}" method="post"> 

    {% if form.errors %} 

      <ul> 

        {% for name, errors in form.errors.items() %} 

          {% for error in errors %} 

            <li>{{ error }}</li> 

          {% endfor %} 

        {% endfor %} 

      </ul> 

    {% endif %} 

    账号:{{ form.accountNumber(size=20) }}<label>{{ form.accountNumber.errors[0] }}</label><br/> 

    密码:<input name="password" type="password"/><br/> 

    {{ form.hidden_tag() }} 

    <button type="submit">登录</button> 

  </form> 

{% endblock %}

到此,一个Flask实现简单登录功能就做完了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
小结Python用fork来创建子进程注意事项
Jul 03 Python
Python爬虫信息输入及页面的切换方法
May 11 Python
python中多个装饰器的执行顺序详解
Oct 08 Python
python 分离文件名和路径以及分离文件名和后缀的方法
Oct 21 Python
python绘图模块matplotlib示例详解
Jul 26 Python
Python datetime包函数简单介绍
Aug 28 Python
完美解决pycharm导入自己写的py文件爆红问题
Feb 12 Python
pandas分组聚合详解
Apr 10 Python
python Django 反向访问器的外键冲突解决
May 20 Python
Python 使用 PyQt5 开发的关机小工具分享
Jul 16 Python
上帝为你开了一扇窗之Tkinter常用函数详解
Jun 02 Python
Python中的 enumerate和zip详情
May 30 Python
python实现逐个读取txt字符并修改
Dec 24 #Python
Python判断一个list中是否包含另一个list全部元素的方法分析
Dec 24 #Python
python读取txt文件中特定位置字符的方法
Dec 24 #Python
python进行文件对比的方法
Dec 24 #Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
Dec 24 #Python
详解Python进阶之切片的误区与高级用法
Dec 24 #Python
Python数据抓取爬虫代理防封IP方法
Dec 23 #Python
You might like
PHP中Session的概念
2006/10/09 PHP
创建数据库php代码 用PHP写出自己的BLOG系统
2010/04/12 PHP
深入PHP内存相关的功能特性详解
2013/06/08 PHP
php 无限级分类,超级简单的无限级分类,支持输出树状图
2014/06/29 PHP
PHP设计模式之迭代器模式
2016/06/17 PHP
prototype1.4中文手册
2006/09/22 Javascript
脚本安需导入(装载)的三种模式的对比
2007/06/24 Javascript
javascript中用星号表示预录入内容的实现代码
2011/01/08 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
2013/10/16 Javascript
简介alert()与console.log()的不同
2015/08/26 Javascript
vue.js 使用v-if v-else发现没有执行解决办法
2017/05/15 Javascript
详解Axios 如何取消已发送的请求
2018/10/20 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
Js视频播放器插件Video.js使用方法详解
2020/02/04 Javascript
Python中使用glob和rmtree删除目录子目录及所有文件的例子
2014/11/21 Python
使用Python编写提取日志中的中文的脚本的方法
2015/04/30 Python
解决python写入mysql中datetime类型遇到的问题
2018/06/21 Python
Python rstrip()方法实例详解
2018/11/11 Python
python绘制地震散点图
2019/06/18 Python
python 动态迁移solr数据过程解析
2019/09/04 Python
win10安装tensorflow-gpu1.8.0详细完整步骤
2020/01/20 Python
Whistles官网:英国女装品牌
2020/08/14 全球购物
双立人加拿大官网:Zwilling加拿大
2020/08/10 全球购物
介绍一下linux的文件权限
2014/07/20 面试题
软件设计的目标是什么
2016/12/04 面试题
犯错检讨书
2014/02/21 职场文书
医学生毕业自我鉴定
2014/03/26 职场文书
开工仪式策划方案
2014/05/23 职场文书
质量主管工作职责
2014/09/26 职场文书
教师个人事迹材料
2014/12/17 职场文书
2015年党员个人自我评价
2015/03/03 职场文书
高一语文教学反思
2016/02/16 职场文书
幼儿园大班教学反思
2016/03/02 职场文书
Java spring定时任务详解
2021/10/05 Java/Android
JavaScript 原型与原型链详情
2021/11/02 Javascript
《黑岩★★射手 DAWN FALL》BD发售宣传CM公开
2022/04/04 日漫