【學(xué)習(xí)筆記】Flask Web Application簡(jiǎn)單的登錄頁(yè)面

Flask Web Application

Flask Web Application代碼

安裝flask環(huán)境

pip install flask

pip install flask-login

pip install flask-sqlalchemy

創(chuàng)建項(xiàng)目總文件夾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"
        
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
        crossorigin="anonymous"
      />
      <link
        rel="stylesheet"
        
        crossorigin="anonymous"
      />      
      <title>{% block title %}主頁(yè){% 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="/">主頁(yè)</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">注冊(cè)</a>
            {% endif %}
          </div>
        </div>
      </nav>      
      {% with messages = get_flashed_messages(with_categories=true) %} {% if
      messages %} {% for category, message in messages %} {% if category ==
      '錯(cuò)誤' %}
      <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 %}主頁(yè){% endblock %} {% block content
  %}
  <!DOCTYPE html>
  <html>
  <body>
  <h1 align="center">記錄內(nèi)容</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 %}注冊(cè){% endblock %} {% block
  content %}
  <form method="POST">
    <h3 align="center">注冊(cè)</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">確認(rèn)密碼</label>
      <input
        type="password"
        class="form-control"
        id="password2"
        name="password2"
        placeholder="確認(rèn)密碼"
      />
    </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('成功創(chuàng)建數(shù)據(jù)庫(kù)呐赡!')
  • 子文件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('密碼錯(cuò)誤,請(qǐng)重試!', category='錯(cuò)誤')
          else:
              flash('郵箱不存在务傲!', category='錯(cuò)誤')          
      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='錯(cuò)誤')
          elif len(email) < 4:
              flash('郵箱至少包含3個(gè)字符.', category='錯(cuò)誤')
          elif len(first_name) < 2:
              flash('請(qǐng)輸入您的姓名(至少包含1個(gè)字符)', category='錯(cuò)誤')
          elif password1 != password2:
              flash('密碼不匹配', category='錯(cuò)誤')
          elif len(password1) < 7:
              flash('請(qǐng)輸入至少7位以上的密碼.', category='錯(cuò)誤')
          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('成功創(chuàng)建賬戶!', 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('請(qǐng)輸入內(nèi)容!', category='錯(cuò)誤')
          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)
      

運(yùn)行 python main.py

run_main

訪問(wèn)127.0.0.1:5000

頁(yè)面展示

login
sign_up
home
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末玫芦,一起剝皮案震驚了整個(gè)濱河市泉哈,隨后出現(xiàn)的幾起案子吴攒,更是在濱河造成了極大的恐慌,老刑警劉巖革半,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碑定,死亡現(xiàn)場(chǎng)離奇詭異流码,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)延刘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)漫试,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人碘赖,你說(shuō)我怎么就攤上這事驾荣。” “怎么了普泡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵播掷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我撼班,道長(zhǎng)歧匈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任砰嘁,我火速辦了婚禮件炉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矮湘。我一直安慰自己斟冕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布缅阳。 她就那樣靜靜地躺著磕蛇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪券时。 梳的紋絲不亂的頭發(fā)上孤里,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天伏伯,我揣著相機(jī)與錄音橘洞,去河邊找鬼。 笑死说搅,一個(gè)胖子當(dāng)著我的面吹牛炸枣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弄唧,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼适肠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了候引?” 一聲冷哼從身側(cè)響起侯养,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎澄干,沒(méi)想到半個(gè)月后逛揩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體柠傍,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年辩稽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惧笛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逞泄,死狀恐怖患整,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喷众,我是刑警寧澤各谚,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站到千,受9級(jí)特大地震影響嘲碧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜父阻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一愈涩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧加矛,春花似錦履婉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至苛茂,卻和暖如春已烤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背妓羊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工胯究, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人躁绸。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓裕循,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親净刮。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剥哑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容