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 相关文章推荐
30分钟搭建Python的Flask框架并在上面编写第一个应用
Mar 30 Python
python使用PIL缩放网络图片并保存的方法
Apr 24 Python
Python pandas常用函数详解
Feb 07 Python
django开发post接口简单案例,获取参数值的方法
Dec 11 Python
PyQt4编程之让状态栏显示信息的方法
Jun 18 Python
图文详解Django使用Pycharm连接MySQL数据库
Aug 09 Python
python 循环数据赋值实例
Dec 02 Python
Python中的 ansible 动态Inventory 脚本
Jan 19 Python
python实现四人制扑克牌游戏
Apr 22 Python
vscode配置anaconda3的方法步骤
Aug 08 Python
Pandas替换及部分替换(replace)实现流程详解
Oct 12 Python
Python之多进程与多线程的使用
Feb 23 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
业余方法DIY电子管FM收音机
2021/03/02 无线电
PHP实现抓取迅雷VIP账号的方法
2015/07/30 PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
2016/02/26 PHP
PHP输出Excel PHPExcel的方法
2018/07/26 PHP
Script的加载方法小结
2011/01/12 Javascript
最新的10款jQuery内容滑块插件分享
2011/09/18 Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2012/07/21 Javascript
JS获取页面input控件中所有text控件并追加样式属性
2013/02/25 Javascript
从数据结构的角度分析 for each in 比 for in 快的多
2013/07/07 Javascript
jquery特效 幻灯片效果示例代码
2013/07/16 Javascript
js单例模式详解实例
2013/11/21 Javascript
jQuery切换网页皮肤并保存到Cookie示例代码
2014/06/16 Javascript
JavaScript中用toString()方法返回时间为字符串
2015/06/12 Javascript
详解jQuery中的empty、remove和detach
2016/04/11 Javascript
js停止冒泡和阻止浏览器默认行为的简单方法
2016/05/15 Javascript
基于JavaScript Array数组方法(新手必看篇)
2016/08/20 Javascript
利用jquery获取select下拉框的值
2016/11/23 Javascript
JS产生随机数的用法小结
2016/12/10 Javascript
关于bootstrap日期转化,bootstrap-editable的简单使用,bootstrap-fileinput的使用详解
2017/05/12 Javascript
ES6中的rest参数与扩展运算符详解
2017/07/18 Javascript
React-intl 实现多语言的示例代码
2017/11/03 Javascript
javascript性能优化之分时函数的介绍
2018/03/28 Javascript
vue自定义正在加载动画的例子
2019/11/14 Javascript
基于进程内通讯的python聊天室实现方法
2015/06/28 Python
opencv实现图片模糊和锐化操作
2018/11/19 Python
Python自动抢红包教程详解
2019/06/11 Python
浅谈Pandas Series 和 Numpy array中的相同点
2019/06/28 Python
python爬虫 正则表达式解析
2019/09/28 Python
pip install命令安装扩展库整理
2021/03/02 Python
德国家用电器购物网站:Premiumshop24
2019/08/22 全球购物
会计电算化专业毕业生自荐信
2013/12/20 职场文书
自动化专业职业生涯规划书范文
2014/01/16 职场文书
小学生国庆节演讲稿
2014/09/05 职场文书
酒店优秀员工推荐信
2015/03/24 职场文书
CSS3 天气图标动画效果
2021/04/06 HTML / CSS
Python趣味挑战之用pygame实现简单的金币旋转效果
2021/05/31 Python