【学习笔记】Flask Web Application简单的登录页面

Flask Web Application

Flask Web Application代码

安装flask环境

pip install flask

pip install flask-login

pip install flask-sqlalchemy

创建项目总文件夹flask web application

子文件夹website

  • 子文件夹static

    • 配置index.js
  function deleteNote(noteId) {
    fetch("/delete-note", {
      method: "POST",
      body: JSON.stringify({ noteId: noteId }),
    }).then((_res) => {
      window.location.href = "/";
    });
  }
  • 子文件夹templates

    • 配置base.html
  <!DOCTYPE html>
  <html>
    <head>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <link
        rel="stylesheet"
        href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
        crossorigin="anonymous"
      />
      <link
        rel="stylesheet"
        href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
        crossorigin="anonymous"
      />      
      <title>{% block title %}主页{% endblock %}</title>
    </head>
    <body>
      <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <button
          class="navbar-toggler"
          type="button"
          data-toggle="collapse"
          data-target="#navbar"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbar">
          <div class="navbar-nav">
            {% if user.is_authenticated %}
            <a class="nav-item nav-link" id="home" href="/">主页</a>
            <a class="nav-item nav-link" id="logout" href="/logout">登出</a>
            {% else %}
            <a class="nav-item nav-link" id="login" href="/login">登入</a>
            <a class="nav-item nav-link" id="signUp" href="/sign-up">注册</a>
            {% endif %}
          </div>
        </div>
      </nav>      
      {% with messages = get_flashed_messages(with_categories=true) %} {% if
      messages %} {% for category, message in messages %} {% if category ==
      '错误' %}
      <div class="alert alert-danger alter-dismissable fade show" role="alert">
        {{ message }}
        <button type="button" class="close" data-dismiss="alert">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      {% else %}
      <div class="alert alert-success alter-dismissable fade show" role="alert">
        {{ message }}
        <button type="button" class="close" data-dismiss="alert">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      {% endif %} {% endfor %} {% endif %} {% endwith %}          
      <div class="container">{% block content %} {% endblock %}</div>
      <script
        src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
        integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
        crossorigin="anonymous"
      ></script>
      <script
        src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"
      ></script>
      <script
        src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"
      ></script>          
      <script
        type="text/javascript"
        src="{{ url_for('static', filename='index.js') }}"
      ></script>
    </body>
  </html>
  • 配置home.html
  {% extends "base.html" %} {% block title %}主页{% endblock %} {% block content
  %}
  <!DOCTYPE html>
  <html>
  <body>
  <h1 align="center">记录内容</h1>
  
  <center><img src='https://c-ssl.duitang.com/uploads/item/201501/20/20150120150852_fjASC.thumb.1000_0.jpeg'></center>
  
  <ul class="list-group list-group-flush" id="notes">
    {% for note in user.notes %}
    <li class="list-group-item">
      {{ note.data }}
      <button type="button" class="close" onClick="deleteNote({{ note.id }})">
        <span aria-hidden="true">&times;</span>
      </button>
    </li>
    {% endfor %}
  </ul>
  <form method="POST">
    <textarea name="note" id="note" class="form-control"></textarea>
    <br />
    <div align="center">
      <button type="submit" class="btn btn-primary">添加记录</button>
    </div>
  </form>
  </body>
  </html>
  {% endblock %}
  • 配置login.html
  {% extends "base.html" %} {% block title %}登入{% endblock %} {% block content
  %}
  <form method="POST">
    <h3 align="center">登入</h3>
    <div class="form-group">
      <label for="email">邮箱</label>
      <input
        type="email"
        class="form-control"
        id="email"
        name="email"
        placeholder="输入邮箱地址"
      />
    </div>
    <div class="form-group">
      <label for="password">密码</label>
      <input
        type="password"
        class="form-control"
        id="password"
        name="password"
        placeholder="输入密码"
      />
    </div>
    <br />
    <button type="submit" class="btn btn-primary">提交</button>
  </form>
  {% endblock %}
  • 配置sign_up.html
  {% extends "base.html" %} {% block title %}注册{% endblock %} {% block
  content %}
  <form method="POST">
    <h3 align="center">注册</h3>
    <div class="form-group">
      <label for="email">邮箱</label>
      <input
        type="email"
        class="form-control"
        id="email"
        name="email"
        placeholder="输入邮箱地址"
      />
    </div>
    <div class="form-group">
      <label for="firstName">姓名</label>
      <input
        type="text"
        class="form-control"
        id="firstName"
        name="firstName"
        placeholder="输入姓名"
      />
    </div>
    <div class="form-group">
      <label for="password1">密码</label>
      <input
        type="password"
        class="form-control"
        id="password1"
        name="password1"
        placeholder="输入密码"
      />
    </div>
    <div class="form-group">
      <label for="password2">确认密码</label>
      <input
        type="password"
        class="form-control"
        id="password2"
        name="password2"
        placeholder="确认密码"
      />
    </div>
    <br />
    <button type="submit" class="btn btn-primary">提交</button>
  </form>
  {% endblock %}
  • 子文件init.py

    • 配置init.py
  from flask import Flask
  from flask_sqlalchemy import SQLAlchemy
  from os import path
  from flask_login import LoginManager
  
  db = SQLAlchemy()
  DB_NAME = "database.db"     
  
  def create_app():
      app = Flask(__name__)
      app.config['SECRET_KEY'] = 'become a developer'
      app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
      db.init_app(app)    
      from .views import views
      from .author import author          
      app.register_blueprint(views, url_prefix='/')
      app.register_blueprint(author, url_prefix='/')          
      from .models import User, Note          
      create_database(app)        
      login_manager = LoginManager()
      login_manager.login_view = 'author.login'
      login_manager.init_app(app)         
      @login_manager.user_loader
      def load_user(id):
          return User.query.get(int(id))          
      return app      
  
  def create_database(app):
      if not path.exists('website/' + DB_NAME):
          db.create_all(app=app)
          print('成功创建数据库!')
  • 子文件author.py

    • 配置author.py
  from flask import Blueprint, render_template, request, flash, redirect, url_for
  from .models import User
  from werkzeug.security import generate_password_hash, check_password_hash
  from . import db
  from flask_login import login_user, login_required, logout_user, current_user
  
  author = Blueprint('author', __name__)      
  
  @author.route('/login', methods=['GET', 'POST'])
  def login():
      if request.method == 'POST':
          email = request.form.get('email')
          password = request.form.get('password')     
          user = User.query.filter_by(email=email).first()
          if user:
              if check_password_hash(user.password, password):
                  flash('登录成功!', category='成功')
                  login_user(user, remember=True)
                  return redirect(url_for('views.home'))
              else:
                  flash('密码错误,请重试!', category='错误')
          else:
              flash('邮箱不存在!', category='错误')          
      return render_template("login.html", user=current_user)
  
  @author.route('/logout')
  @login_required
  def logout():
      logout_user()
      return redirect(url_for('author.login'))
  
  @author.route('/sign-up', methods=['GET', 'POST'])
  def sign_up():
      if request.method == 'POST':
          email = request.form.get('email')
          first_name = request.form.get('firstName')
          password1 = request.form.get('password1')
          password2 = request.form.get('password2')
  
          user = User.query.filter_by(email=email).first()
          if user:
              flash('邮箱已存在', category='错误')
          elif len(email) < 4:
              flash('邮箱至少包含3个字符.', category='错误')
          elif len(first_name) < 2:
              flash('请输入您的姓名(至少包含1个字符)', category='错误')
          elif password1 != password2:
              flash('密码不匹配', category='错误')
          elif len(password1) < 7:
              flash('请输入至少7位以上的密码.', category='错误')
          else:
              new_user = User(email=email, first_name=first_name, password=generate_password_hash(
                  password1, method='sha256'))
              db.session.add(new_user)
              db.session.commit()
              login_user(new_user, remember=True)
              flash('成功创建账户!', category='成功')
              return redirect(url_for('views.home'))
      
      return render_template("sign_up.html", user=current_user)
  • 子文件models.py

    • 配置models.py
  from . import db
  from flask_login import UserMixin
  from sqlalchemy.sql import func
  
  
  class Note(db.Model):
      id = db.Column(db.Integer, primary_key=True)
      data = db.Column(db.String(10000))
      date = db.Column(db.DateTime(timezone=True), default=func.now())
      user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
  
  
  class User(db.Model, UserMixin):
      id = db.Column(db.Integer, primary_key=True)
      email = db.Column(db.String(150), unique=True)
      password = db.Column(db.String(150))
      first_name = db.Column(db.String(150))
      notes = db.relationship('Note')
  • 子文件views.py

    • 配置views.py
  from flask import Blueprint, render_template, request, flash, jsonify
  from flask_login import login_required, current_user
  from .models import Note
  from . import db
  import json
  
  views = Blueprint('views', __name__)
  
  @views.route('/', methods=['GET', 'POST'])
  @login_required
  def home():
      if request.method == 'POST':
          note = request.form.get('note')
  
          if len(note) < 1:
              flash('请输入内容!', category='错误')
          else:
              new_note = Note(data=note, user_id=current_user.id)
              db.session.add(new_note)
              db.session.commit()
              flash('成功添加记录!', category='成功')
      
      return render_template("home.html", user=current_user)
  
  @views.route('/delete-note', methods=['POST'])
  def delete_note():
      note = json.loads(request.data)
      noteId = note['noteId']
      note = Note.query.get(noteId)
      if note:
          if note.user_id == current_user.id:
              db.session.delete(note)
              db.session.commit()
  
      return jsonify({})
  • 子文件main.py
    • 配置main.py

      from website import create_app   
      app = create_app()   
      if __name__=='__main__':
          app.run(debug=True)
      

运行 python main.py

run_main

访问127.0.0.1:5000

页面展示

login
sign_up
home
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容