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计算三角函数之acos()方法的使用
May 15 Python
Python对象转JSON字符串的方法
Apr 27 Python
Python中 Lambda表达式全面解析
Nov 28 Python
Python实现模拟浏览器请求及会话保持操作示例
Jul 30 Python
Python读取csv文件分隔符设置方法
Jan 14 Python
Python判断有效的数独算法示例
Feb 23 Python
Django实现学生管理系统
Feb 26 Python
Python二叉树的镜像转换实现方法示例
Mar 06 Python
python判断单向链表是否包括环,若包含则计算环入口的节点实例分析
Oct 23 Python
python实现二分类和多分类的ROC曲线教程
Jun 15 Python
pycharm 实现复制一行的快捷键
Jan 15 Python
python如何利用cv2.rectangle()绘制矩形框
Dec 24 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
Phpbean路由转发的php代码
2008/01/10 PHP
PHP中用header图片地址 简单隐藏图片源地址
2008/04/09 PHP
简单实用的网站PHP缓存类实例
2014/07/18 PHP
PHP使用ob_start生成html页面的方法
2014/11/07 PHP
codeigniter显示所有脚本执行时间的方法
2015/03/21 PHP
php封装的图片(缩略图)处理类完整实例
2016/10/19 PHP
PHP获取数组中单列值的方法
2017/06/10 PHP
PHP中使用jQuery+Ajax实现分页查询多功能操作(示例讲解)
2017/09/17 PHP
PHP常见字符串操作函数与用法总结
2019/03/04 PHP
用Div仿showModalDialog模式菜单的效果的代码
2007/03/05 Javascript
ie focus bug 解决方法
2009/09/03 Javascript
用jQuery实现的智能隐藏、滑动效果的返回顶部代码
2014/03/18 Javascript
JavaScript中constructor()方法的使用简介
2015/06/05 Javascript
JavaScript对象属性检查、增加、删除、访问操作实例
2015/07/08 Javascript
javascript学习指南之回调问题
2016/04/23 Javascript
浅谈JS运算符&amp;&amp;和|| 及其优先级
2016/08/10 Javascript
详解Weex基于Vue2.0开发模板搭建
2017/03/20 Javascript
浅析vue-router jquery和params传参(接收参数)$router $route的区别
2018/08/03 jQuery
Vue一次性简洁明了引入所有公共组件的方法
2018/11/28 Javascript
JS深入学习之数组对象排序操作示例
2020/05/01 Javascript
vue封装自定义指令之动态显示title操作(溢出显示,不溢出不显示)
2020/11/12 Javascript
python使用beautifulsoup从爱奇艺网抓取视频播放
2014/01/23 Python
Python3实现的简单验证码识别功能示例
2018/05/02 Python
Python实现求两个数组交集的方法示例
2019/02/23 Python
在PyTorch中使用标签平滑正则化的问题
2020/04/03 Python
python 检测nginx服务邮件报警的脚本
2020/12/31 Python
拥有超过850家商店的美国在线派对商店:Party City
2018/10/21 全球购物
与C++相比,Java中的数组有什么不同
2014/03/25 面试题
校园安全广播稿
2014/02/08 职场文书
亮化工程实施方案
2014/03/17 职场文书
食品安全演讲稿
2014/09/01 职场文书
工作能力自我评价2015
2015/03/05 职场文书
2016父亲节感恩话语
2015/12/09 职场文书
各种货币符号快捷输入
2022/02/17 杂记
MySQL中优化SQL语句的方法(show status、explain分析服务器状态信息)
2022/04/09 MySQL
nginx location 带斜杠【 / 】与不带的区别
2022/04/13 Servers