Flask08——数据库操作-增删改查作者书籍

增加书籍表

下面我们用flask_sqlalchemy提供的建表语句来通过类的形式创建表。

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True, comment='作者主键ID')
    name = db.Column(db.String(30), nullable=False, comment='作者姓名')

class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True, comment='书籍主键ID')
    title = db.Column(db.String(30), nullable=False, comment='书籍标题')
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))  # 外键,关联作者表的主键ID
db.ForeignKey:定义此字段为外键,关联author表的主键ID字段。

修改所有作者模板

<!--all_authors.html文件-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>所有作者</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        {% for author in authors %}
            <p>{{ author.id }}、{{ author.name }} |
                <a href="{{ url_for('edit_author', author_id=author.id) }}">编辑</a> |
                <a href="{{ url_for('delete_author', author_id=author.id) }}">删除</a> |
                <a href="{{ url_for('add_book', author_id=author.id) }}">添加{{ author.name }}的书籍</a> |
                <a href="{{ url_for('author_books', author_id=author.id) }}">{{ author.name }}的书籍</a> |
            </p>
        {% endfor %}
        {% for message in get_flashed_messages() %}
            <span style="color:red">{{ message }}</span>
        {% endfor %}
    {% endblock content %}
</body>
</html>

添加书籍

# 添加书籍
@app.route('/add_book', methods=['GET', 'POST'])
def add_book():
    author_id = request.args.get('author_id')  # 首页要拿到作者id,因为我们要添加书籍到某个用户下面
    print(author_id)
    if request.method == 'POST':
        title = request.form.get('title')  # 从表单里面接收过来的
        new_book = Book(title=title, author_id=author_id)  # 要传递两个字段的数据
        try:
            db.session.add(new_book)
            db.session.commit()
            flash('添加书籍成功!')
        except Exception as e:
            flash('添加书籍不成功!')
        return redirect(url_for('all_authors'))
    return render_template('add_book.html')
<!--add_book.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加书籍</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        <form action="" method="post">
            书籍名称:<input type="text" name="title" value="">
            <input type="submit" value="确认添加">
        </form>
        {% for message in get_flashed_messages() %}
            <span style="color:red">{{ message }}</span>
        {% endfor %}
    {% endblock %}
</body>
</html>

作者书籍方法一


# 作者书籍 方法一
@app.route('/author_books')
def author_books():
    author_id = request.args.get('author_id')
    books = Book.query.filter(Book.author_id == author_id).all()
    # filter当中  表.字段(以哪个字段为条件进行查询)== 传递的值
    print(books)
    return render_template('author_books.html', books=books)
<!--author_books.html文件-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>作者书籍</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        <!--对应视图函数方法一-->
        {% for book in books %}
            <p>{{ book.title }}</p>  <!--这里无法获取到作者数据,因为此页面只有书籍数据-->
        {% endfor %}
    {% endblock %}
</body>
</html>

作者书籍方法二

# 作者书籍 方法二
@app.route('/author_books')
def author_books():
    # 先添加 many_books = db.relationship('Book', backref='one_book_author') 到author表
    # many_books是虚拟字段,此虚拟字段相当于一个作者的所有书籍的列表,one_book_author字段相当于给book表使用的虚拟字段,代表了一本书籍的作者。
    author_id = request.args.get('author_id')  # 拿到作者ID
    one_author = Author.query.get(author_id)  # 通过作者ID取到作者对象
    return render_template('author_books2.html', one_author=one_author)
<!--author_books2.html文件-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ one_author.name }}作者书籍</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        {% for book in one_author.many_books %}  <!--通过作者对象拿到作者下面所有书籍,并进行遍历-->
            <p>{{ book.id }}、{{ book.title }} |
                <a href="{{ url_for('edit_book', book_id=book.id) }}">编辑{{ one_author.name }}书籍</a> |
                <a href="{{ url_for('delete_book', book_id=book.id) }}">删除{{ one_author.name }}书籍</a> |
            </p>
        {% endfor %}
    {% endblock %}
</body>
</html>

编辑书籍

# 编辑书籍
@app.route('/edit_book', methods=['GET', 'POST'])
def edit_book():
    book_id = request.args.get('book_id')
    one_book = Book.query.get(book_id)  # 通过书籍id获取单个书籍的记录
    if request.method == 'POST':
        title = request.form.get('title')  # 取到传递过来的书籍的标题
        one_book.title = title  # 将传递过来的书籍的标题赋值到现有记录上
        db.session.add(one_book)
        db.session.commit()
        return redirect(url_for('author_books', author_id=one_book.author_id))
        # 跳转到某一个作者的所有书籍下面,因为当前页面没有作者的数据,所以只能从单个书籍里面通过单本书籍的外键拿到作者的id
    return render_template('edit_book.html', one_book=one_book)
<!--edit_book.html文件-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>编辑书籍</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        <form action="" method="post">
            书籍名称:<input type="text" name="title" value="{{ one_book.title }}">
            <input type="submit" value="确认修改">
        </form>
    {% endblock content %}
</body>
</html>

删除单本书籍

# 删除单本书籍
@app.route('/delete_book')
def delete_book():
    book_id = request.args.get('book_id')
    one_book = Book.query.get(book_id)
    db.session.delete(one_book)
    db.session.commit()
    return redirect(url_for('author_books', author_id=one_book.author_id))

批量删除多本书籍

<!--修改模板-->
<!--author_books3.html文件-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ one_author.name }}作者书籍</title>
</head>
<body>
    {% extends 'base.html' %}
    {% block content %}
        <form action="{{ url_for('delete_books') }}" method="post">  <!--注意提交的视图函数已经不是默认的了,还有方法-->
            {% for book in one_author.many_books %}  <!--通过作者对象拿到作者下面所有书籍,并进行遍历-->
                <p>
                    <input type="checkbox" name="book_ids" value="{{ book.id }}">  <!--加复选框,name是多个复选框公用的,是一个列表  值就是当前书籍的id-->
                    {{ book.id }}、{{ book.title }} |
                    <a href="{{ url_for('edit_book', book_id=book.id) }}">编辑{{ one_author.name }}书籍</a> |
                    <a href="{{ url_for('delete_book', book_id=book.id) }}">删除{{ one_author.name }}书籍</a> |
                </p>
            {% endfor %}
            <input type="submit" value="批量删除">  <!--提交按钮注意要在form表单中-->
        </form>
    {% endblock %}
</body>
</html>
# 批量删除多本书籍
@app.route('/delete_books', methods=['POST'])
def delete_books():
    book_ids = request.form.getlist('book_ids')  # 接收复选框参数的语法要注意
    one_book = ''
    for book_id in book_ids:  # 遍历出单本书籍的id,再进行逐一删除即可
        print(book_id)
        print(type(book_id))
        one_book = Book.query.get(int(book_id))
        db.session.delete(one_book)
        db.session.commit()
    return redirect(url_for('author_books', author_id=one_book.author_id))  # 注意跳转要放到最下面,不要放到循环当中。
    # 如果放到循环当中,那么就只删除一条就会跳转走了,也就是不会再继续删除了。

修改删除作者

上一讲,当我们只有一张表的时候,删除作者的时候不会有任何问题,可是现在我们有两张表了,而且书籍表有一个字段是外键,指向作者表,那么如果一个作者存在书籍记录在书籍表的话,删除作者的时候就会有问题。当我们没有配置 many_books = db.relationship('Book', backref='one_book_author') 这个关系的话,会提示删除不了。如果配置了的话,此作者可以删除,但是在书籍表中,此作者下面的书籍记录的author_id这个外键会置为null,这样显示是不合适的,会造成数据的错乱。不建议这样做,所以我们就要修改下删除作者的视图函数了,先遍历删除此作者下面的书籍,再删除此作者即可。

# 删除作者(先删除作者的书籍,后删除作者)
@app.route('/delete_author')
def delete_author():
    author_id = request.args.get('author_id')  # 跟编辑一样需要获取当前用户的id
    one_author = Author.query.get(author_id)  # 通过id获取当前记录(对象)
    for book in one_author.many_books:  # 通过many_books拿到此作者所有书籍,遍历删除
        one_book = Book.query.get(book.id)  # 通过单本书籍id获取单本书籍记录
        try:
            db.session.delete(one_book)
            db.session.commit()
            flash('删除书籍成功!')
        except Exception as e:
            flash('删除书籍不成功!')
    try:
        db.session.delete(one_author)  # 删除作者记录(对象)
        db.session.commit()
        flash('删除作者成功!')
    except Exception as e:
        flash('删除作者不成功!')
    return redirect(url_for('all_authors'))  # 删除之后跳转到所有作者页面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值