Flask数据库一对多(图书馆)小项目搭建

项目分析:

  • 分析图书馆案例
    • 1.数据库配置
      • 作者模型(一方)
      • 书籍模型(多方)
    • 2.添加测试数据
    • 3.添加作者,书籍
    • 4.删除作者,删除书籍

显示作者和书籍

  • 1.查询所有作者信息
  • 2.携带作者信息,渲染页面

添加书籍

  • 1.如果作者存在,书籍存在, 不能添加
  • 2.如果作者存在,书籍不存在,可以添加
  • 3.如果作者不存在,可以添加

删除书籍

  • 1根据书籍编号获取书籍对象
  • 2.删除书籍对象
  • 3.重定向到页面展示

删除作者

  • 1.根据作者编号获取作者对象
  • 2.遍历删除,作者书籍对象
  • 3.删除作者,提交数据库
  • 4.重定向到页面展示

CSRFProtect应用

  • 作用: 防止csrf攻击的[项目倒数第二天看源代码校验过程]
  • 使用步骤:
    • 1.导入类CSRFProtect
    • 2.使用CSRFProtect保护app
      • 一旦使用POST,PUT,DELTE,PATCH方式提交的时候就需要校验csrf_token
    • 3.需要设置SECRET_KEY,用来加密csrf_token
    • 4.设置csrf_token到表单中
"""
分析图书馆案例

- 1.数据库配置
  - 作者模型(一方)
  - 书籍模型(多方)
- 2.添加测试数据
- 3.添加作者,书籍
- 4.删除作者,删除书籍
"""

from flask import Flask, render_template, request, redirect, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)

#加盐
app.config["SECRET_KEY"] = "tianwanggaidihu"

# 使用CSRFProtect保护app
CSRFProtect(app)

# 1.设置数据库配置信息
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/library"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
# app.config["SQLALCHEMY_ECHO"] = True #写上之后会在控制台输出对应生成的sql语句

# 2.创建SQLAlchemy对象,关联app
db = SQLAlchemy(app)


# 3.编写模型类
# 作者模型(一方)
class Author(db.Model):
    __tablename__ = "authors"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))

    # 关系属性
    books = db.relationship("Book", backref="author", lazy='dynamic')


# 书籍模型(多方)
class Book(db.Model):
    __tablename__ = "books"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))

    # 外键
    author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
    # author_id = db.Column(db.Integer,db.ForeignKey("authors.id")) #和上面的方式等价


# 4.展示页面
@app.route('/')
def show_index():
    # 1.查询所有的作者信息
    authors = Author.query.all()

    # 2.携带作者信息,渲染页面
    return render_template("library.html", authors=authors)


# 5.添加数据
@app.route('/add_data', methods=["POST"])
def add_data():
    # 1.获取提交的数据
    author_name = request.form.get("author")
    book_name = request.form.get("book")

    # 1.1判断输入的内容是否为空
    if not all([author_name, book_name]):
        flash("作者或者书籍不能为空")
        return redirect("/")

    # 2.根据作者的信息,查询作者对象
    author = Author.query.filter(Author.name == author_name).first()

    # 3.判断作者是否存在
    if author:

        # 4.通过书籍名称查询书籍对象, 获取该作者,有没有写过该书
        book = Book.query.filter(Book.name == book_name, Book.author_id == author.id).first()

        # 5.判断书籍对象是否存在
        if book:
            flash("该作者,有该书了")
        else:
            # 创建书籍对象,添加到数据库
            book = Book(name=book_name, author_id=author.id)
            db.session.add(book)
            db.session.commit()
    else:
        # 创建作者,对象,添加到书籍库
        author = Author(name=author_name)
        db.session.add(author)
        db.session.commit()

        # 创建书籍对象,添加到数据库
        book = Book(name=book_name, author_id=author.id)
        db.session.add(book)
        db.session.commit()

    # 6.重定向到首页展示
    return redirect("/")


# 6.删除书籍
@app.route('/delete_book/<int:book_id>')
def delete_book(book_id):
    # 1.根据书籍编号取出书籍对象
    book = Book.query.get(book_id)

    # 2.删除书籍
    db.session.delete(book)
    db.session.commit()

    # 3.重定向到页面显示
    return redirect("/")


# 7.删除作者
@app.route('/delete_author/<int:author_id>')
def delete_author(author_id):
    # 1.根据作者编号取出作者对象
    author = Author.query.get(author_id)

    # 2.遍历作者书籍,删除
    for book in author.books:
        db.session.delete(book)

    # 3.删除作者,提交数据库
    db.session.delete(author)
    db.session.commit()

    # 4.重定向展示页面
    return redirect("/")


if __name__ == '__main__':
    # 为了演示方便,先删除,后创建
    db.drop_all()
    db.create_all()

    # 添加测试数据库
    # 生成数据
    au1 = Author(name='老王')
    au2 = Author(name='老尹')
    au3 = Author(name='老刘')
    # 把数据提交给用户会话
    db.session.add_all([au1, au2, au3])
    # 提交会话
    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)
    # 把数据提交给用户会话
    db.session.add_all([bk1, bk2, bk3, bk4, bk5])
    # 提交会话
    db.session.commit()

    app.run(debug=True)

library.html代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    {# action: 提交到的地址, method: 表示提交的方式 #}
    <form action="/add_data" method="post">
    
        {# 设置隐藏字段csrf_token , 只要使用了CSRFProtect,然后使用模板渲染的时候就可以直接使用csrf_token()方法#}
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
    
        作者: <input type="text" name="author"><br>
        书籍: <input type="text" name="book"><br>
        <input type="submit" value="添加"><br>
        {% for message in get_flashed_messages() %}
            <span style="color: red;">{{ message }}</span>
        {% endfor %}
    
    </form>
    
    <hr>
    
    {# 数据展示 #}
    <ul>
        {# 遍历作者 #}
        {% for author in authors %}
            {#        <li>作者: {{ author.name }} <a href="/delete_author/{{ author.id }}">删除</a></li>#}
            <li>作者: {{ author.name }} <a href="{{ url_for("delete_author",author_id=author.id) }}">删除</a></li>
    
            {# 遍历作者的书籍 #}
            <ul>
                {% for book in author.books %}
                    <li>书籍: {{ book.name }} <a href="/delete_book/{{ book.id }}">删除</a></li>
                {% endfor %}
    
            </ul>
        {% endfor %}
    
    </ul>
    
    
    </body>
</html>

页面展示

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值