Flask之初體驗(yàn)

這周學(xué)的內(nèi)容是flask,項(xiàng)目需要在原來的基礎(chǔ)上增加一個(gè)新功能,實(shí)際上就是在原來的一系列文件上改改就能實(shí)現(xiàn),功能也很簡單,連接頁面與數(shù)據(jù)庫,并且在頁面上實(shí)現(xiàn)增刪改查等功能。

項(xiàng)目是用flask實(shí)現(xiàn)的,所以先學(xué)了flask,好在flask是一個(gè)相對(duì)來說功能比較簡單的框架,因此學(xué)的時(shí)候基礎(chǔ)內(nèi)容比較少,但是還是在理解上遇到一些困難。在這里記錄一下flask的原理和案例

# -*- coding:utf-8 -*-

from flask import Flask, render_template, flash, request,  redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

# python2中的固定寫法,當(dāng)程序中出現(xiàn)中文時(shí),用來修改默認(rèn)編碼方式為utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")

# 固定寫法,實(shí)例化一個(gè)flask類
app = Flask(__name__)

# 數(shù)據(jù)庫配置: 數(shù)據(jù)庫地址
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1/flask_books'
#關(guān)閉自動(dòng)跟蹤修改(提升運(yùn)行速度)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
#設(shè)置跨網(wǎng)頁傳輸?shù)拿荑€,不設(shè)會(huì)報(bào)錯(cuò)
app.secret_key = 'itheima'

# 創(chuàng)建數(shù)據(jù)庫對(duì)象
db = SQLAlchemy(app)

'''
1. 配置數(shù)據(jù)庫
    a. 導(dǎo)入SQLAlchemy擴(kuò)展
    b. 創(chuàng)建db對(duì)象, 并配置參數(shù)
    c. 終端創(chuàng)建數(shù)據(jù)庫
2. 添加書和作者模型
    a. 模型繼承db.Model
    b. __tablename__:表名
    c. db.Column:字段
    d. db.relationship: 關(guān)系引用
3. 添加數(shù)據(jù)
4. 使用模板顯示數(shù)據(jù)庫查詢的數(shù)據(jù)
    a. 查詢所有的作者信息, 讓信息傳遞給模板
    b. 模板中按照格式, 依次for循環(huán)作者和書籍即可 (作者獲取書籍, 用的是關(guān)系引用)
5. 使用WTF顯示表單
    a. 自定義表單類
    b. 模板中顯示
    c. secret_key / 編碼 / csrf_token
6. 實(shí)現(xiàn)相關(guān)的增刪邏輯
    a. 增加數(shù)據(jù)
    b. 刪除書籍  url_for的使用 /  for else的使用 / redirect的使用
    c. 刪除作者 
'''


# 定義書和作者模型
# 作者模型
class Author(db.Model):
    # 表名
    __tablename__ = 'authors'

    # 字段
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)

    # 關(guān)系引用(反關(guān)聯(lián),一對(duì)多時(shí)在一的那邊設(shè)置,反關(guān)聯(lián)根據(jù)外鍵生成的約束連接)
    # books是給自己(Author模型)用的, author是給Book模型用的,即可以使用author.books和book.author但在表中不會(huì)生成真正的字段
    books = db.relationship('Book', backref='author')

    # 提升打印時(shí)的美觀度
    def __repr__(self):
        return 'Author: %s' % self.name


# 書籍模型
class Book(db.Model):
    __tablename__ = 'books'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(16), unique=True)
    # 外鍵(括號(hào)里指定主鍵是哪個(gè)表的哪個(gè)字段)
    author_id = db.Column(db.Integer, db.ForeignKey('authors.id'))

    def __repr__(self):
        return 'Book: %s %s' % (self.name, self.author_id)


# 自定義表單類
class AuthorForm(FlaskForm):
    author = StringField('作者', validators=[DataRequired()])
    book = StringField('書籍', validators=[DataRequired()])
    submit = SubmitField('提交')


# 刪除作者
# app.route這個(gè)裝飾器會(huì)將后綴為/delete_author/<author_id>的request都使用 delete_author這個(gè)函數(shù)來執(zhí)行
# <author_id>捕獲url里傳過來的參數(shù),放到后續(xù)的delete_author里
app.route('/delete_author/<author_id>')
def delete_author(author_id):

    # 查詢數(shù)據(jù)庫, 是否有該ID的作者, 如果有就刪除(先刪書, 再刪作者), 沒有提示錯(cuò)誤
    # 1. 查詢數(shù)據(jù)庫
    author = Author.query.get(author_id)

    # 2. 如果有就刪除(先刪書, 再刪作者)
    if author:
        try:
            # 查詢之后直接刪除
            Book.query.filter_by(author_id=author.id).delete()

            # 刪除作者
            db.session.delete(author)
            db.session.commit()
        except Exception as e:
            print e
            # html中有捕獲flash閃現(xiàn)的語句
            flash('刪除作者出錯(cuò)')
            db.session.rollback()

    else:
        # 3. 沒有提示錯(cuò)誤
        flash('作者找不到')
    # redirect中是一個(gè)重定向的網(wǎng)頁,url_for是提取這個(gè)通過route綁定了“index”這個(gè)函數(shù)的網(wǎng)頁
    return redirect(url_for('index'))


# 刪除書籍 --> 網(wǎng)頁中刪除-->點(diǎn)擊需要發(fā)送書籍的ID給刪除書籍的路由 --> 路由需要接受參數(shù)
@app.route('/delete_book/<book_id>')
def delete_book(book_id):

    # 1. 查詢數(shù)據(jù)庫, 是否有該ID的書, 如果有就刪除, 沒有提示錯(cuò)誤
    book = Book.query.get(book_id)

    # 2. 如果有就刪除
    if book:
        try:
            db.session.delete(book)
            db.session.commit()
        except Exception as e:
            print e
            flash('刪除書籍出錯(cuò)')
            db.session.rollback()

    else:
        # 3. 沒有提示錯(cuò)誤
        flash('書籍找不到')

    # redirect: 重定向, 需要傳入網(wǎng)絡(luò)/路由地址
    # url_for('index'): 需要傳入視圖函數(shù)名, 返回改視圖函數(shù)對(duì)應(yīng)的路由地址
    print url_for('index')
    return redirect(url_for('index'))

    # 如何返回當(dāng)前網(wǎng)址 --> 重定向
    # return redirect('wwww.itheima.com')
    # return redirect('/')


@app.route('/', methods=['GET', 'POST'])
def index():
    # 創(chuàng)建自定義的表單類
    author_form = AuthorForm()

    '''
    表單填充和顯示的流程:
    1、打開網(wǎng)頁,會(huì)向URL發(fā)送一個(gè)GET請(qǐng)求,因?yàn)槭荊ET請(qǐng)求,所以author_form為空,網(wǎng)頁上的表單中只顯示框架,框架中無值
    2、在表單中鍵入值,發(fā)送POST請(qǐng)求,滿足條件后,author_form中保存了表單中的值,return 之后又把值傳回給頁面,頁面再渲染上值,保證了鍵入的值一直存在于表單中,而框架里也可以隨時(shí)調(diào)用。

    '''
    驗(yàn)證邏輯:
    1. 調(diào)用WTF的函數(shù)實(shí)現(xiàn)驗(yàn)證
    2. 驗(yàn)證通過獲取數(shù)據(jù)
    3. 判斷作者是否存在
    4. 如果作者存在, 判斷書籍是否存在, 沒有重復(fù)書籍就添加數(shù)據(jù), 如果重復(fù)就提示錯(cuò)誤
    5. 如果作者不存在, 添加作者和書籍
    6. 驗(yàn)證不通過就提示錯(cuò)誤
    '''

    # 1. 調(diào)用WTF的函數(shù)實(shí)現(xiàn)驗(yàn)證
    if author_form.validate_on_submit():

        # 2. 驗(yàn)證通過獲取數(shù)據(jù)
        author_name = author_form.author.data
        book_name = author_form.book.data

        # 3. 判斷作者是否存在
        author = Author.query.filter_by(name=author_name).first()

        # 4. 如果作者存在
        if author:
            #  判斷書籍是否存在
            book = Book.query.filter_by(name=book_name).first()

            # 如果重復(fù)就提示錯(cuò)誤
            if book:
                flash('已存在同名書籍')

            # 沒有重復(fù)書籍就添加數(shù)據(jù)
            else:
                try:
                    new_book = Book(name=book_name, author_id=author.id)
                    db.session.add(new_book)
                    db.session.commit()
                except Exception as e:
                    print e
                    flash('添加書籍失敗')
                    db.session.rollback()

        else:
            # 5. 如果作者不存在, 添加作者和書籍
            try:
                new_author = Author(name=author_name)
                db.session.add(new_author)
                db.session.commit()

                new_book = Book(name=book_name, author_id=new_author.id)
                db.session.add(new_book)
                db.session.commit()
            except Exception as e:
                print e
                flash('添加作者和書籍失敗')
                db.session.rollback()

    else:
        # 6. 驗(yàn)證不通過就提示錯(cuò)誤
        if request.method == 'POST':
            flash('參數(shù)不全')

    # 查詢所有的作者信息, 讓信息傳遞給模板
    authors = Author.query.all()

    return render_template('books.html', authors=authors, form=author_form)


if __name__ == '__main__':

    db.drop_all()
    db.create_all()

    # 生成數(shù)據(jù)
    au1 = Author(name='老王')
    au2 = Author(name='老惠')
    au3 = Author(name='老劉')
    # 把數(shù)據(jù)提交給用戶會(huì)話
    db.session.add_all([au1, au2, au3])
    # 提交會(huì)話
    db.session.commit()
    bk1 = Book(name='老王回憶錄', author_id=au1.id)
    bk2 = Book(name='我讀書少,你別騙我', author_id=au1.id)
    bk3 = Book(name='如何才能讓自己更騷', author_id=au2.id)
    bk4 = Book(name='怎樣征服美麗少女', author_id=au3.id)
    bk5 = Book(name='如何征服英俊少男', author_id=au3.id)
    # 把數(shù)據(jù)提交給用戶會(huì)話
    db.session.add_all([bk1, bk2, bk3, bk4, bk5])
    # 提交會(huì)話
    db.session.commit()

    app.run(debug=True)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容