Python轻量级Web框架Flask(9)——图书馆项目

news2024/11/24 13:29:01

1、项目要求:

  • 创建一个项目,用来说明出版社,书籍和作者的关系。
  • 作者和书籍之间的关系:1对多(一本书由一个作者完成,一本书可以有多个创作者)
  • 出版社和书籍之间的关系:多对多(一个出版社可以出版多本书,一本书可以由多个出版社出版)
  • 要求:
    • 1.在书籍的book_index.html中有一个”查看所有书籍“的超链接按钮,点击进入书籍列表book_list.html页表。
    • 2.在书籍的book_list.html中显示所有书名,点击书名可以进入书籍详情book_detail.html。
    • 3.在书籍book_detail.html中可以点击该书的作者和出版社,进入作者详情的author_detail.html和出版社详情publisher_detail.html页面。

2、项目模板:

  • 本项目模板框架如下:
    在这里插入图片描述
  • 项目模板可参考:Python轻量级Web框架Flask(8)——Flask模型项目模板(拆分&数据迁移)

3、第一步:在models中写好表结构:

# models.py : 模型,数据库

'''
    模型      ===      数据库
    类        ——>     表结构
    类属性     ——>    表字段
    一个对象   ——>    表的一行数据
'''


from .exts import db

# 模型Model:类
# 必须继承 db.Model User才能从普通的类变成模型

# 作者
class Author(db.Model):
    __tablename__ = 'author'  # 表名,如果不写表名,也会自动生成(类名小写),表名一定要小写!
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30))
    age = db.Column(db.Integer, default=1)
    sex = db.Column(db.Boolean, default=True)   # True表示男
    email = db.Column(db.String(200))
    # 关系:Author可以调用books,Book可以反向调用my_auther
    books = db.relationship('Book', backref='my_auther', lazy='dynamic')
# 中间表(书籍-出版社)
book_publish = db.Table(
    'book_publisher',
    db.Column('book_id', db.Integer, db.ForeignKey('book.id'), primary_key=True),
    db.Column('publisher_id', db.Integer, db.ForeignKey('publisher.id'), primary_key=True)
)
# 书籍
class Book(db.Model):
    __tablename__ = 'book'  # 表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), unique=True)
    date = db.Column(db.DateTime)   # 书籍日期
    # 1对多:外键
    author_id = db.Column(db.Integer, db.ForeignKey(Author.id))
# 出版社
class Publisher(db.Model):
    __tablename__ = 'publisher'  # 表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(30), unique=True)
    address = db.Column(db.String(200))
    city = db.Column(db.String(100))
    province = db.Column(db.String(100))
    country = db.Column(db.String(100))
    website = db.Column(db.String(100))
    # 多对多,关联book表,secondary是设置中间表
    books = db.relationship('Book', backref='publishers', secondary=book_publish, lazy='dynamic')


4、第二步:进行数据迁移

  • 1、在pycharm中将项目_05_TuShuGuanXiangMu拖到终端中(改变终端路径)
  • 2、在终端执行:flask db init 数据库初始化
  • 3、在终端执行:flask db migrate
  • 4、在终端执行:flask db upgrade
  • 最终执行结束会生成migrations文件夹

5、第三步:创建书籍相关页面:

在这里插入图片描述


6、第四步:给数据库添加测试数据:以作者数据库为例说明

在这里插入图片描述
总结:添加数据可以在pycharm专业版自带的数据库中操作如上,也可以在workbench中操作(一种界面操作,一种SQL语句操作)。


注意:本项目第五步和第六步是同步测试编写的

7、第五步:其余python代码展示

app

from App import creat_app

app = creat_app()


if __name__ == '__main__':
    app.run(debug=True)

__init __

# __init__.py : 初始化文件,创建Flask应用
from flask import Flask
from .views import blue
from .exts import init_exts

def creat_app():
    app = Flask(__name__)

    # 注册蓝图
    app.register_blueprint(blueprint=blue)

    # 配置数据库
    # db_uri = 'sqlite:///sqlite3.db'
    db_uri = 'mysql+pymysql://root:123456@localhost:3306/bookdb' # mysql的配置
    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 禁止对象追踪修改

    # 初始化插件
    init_exts(app=app)

    return app

exts

from flask_sqlalchemy import SQLAlchemy # ORM(对象关系映射)
from flask_migrate import Migrate   # 数据迁移

db = SQLAlchemy()
migrate = Migrate()

def init_exts(app):
    db.init_app(app=app)
    migrate.init_app(app=app,db=db)

views

# 在views.py中放路由和视图函数

from flask import Blueprint, request, render_template
from .models import * #后面是用views来控制数据库的,所以要在views中导入models文件

# 蓝图
blue = Blueprint('book', __name__)

@blue.route('/')
@blue.route('/bookindex/')
def book_index():
    return render_template('book_index.html')

@blue.route('/booklist/')
def book_list():
    books = Book.query.all()
    return render_template('book_list.html', books=books)

@blue.route('/bookdetail/<int:bid>/')   # 路由传参
def book_detail(bid):
    book = Book.query.get(bid)
    return render_template('book_detail.html', book=book)

# 作者详情
@blue.route('/authordetail/<int:aid>/')   # 路由传参
def author_detail(aid):
    author = Author.query.get(aid)
    return render_template('author_detail.html', author=author)

# 出版社详情
@blue.route('/publisherdetail/<int:pid>/')   # 路由传参
def publisher_detail(pid):
    publisher = Publisher.query.get(pid)
    return render_template('publisher_detail.html', publisher=publisher)

8、第六步:templates中所有页面代码展示

author_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>作者详情</title>
</head>
<body>
    <h2>作者详情</h2>
    <p>作者姓名:{{ author.name }}</p>
    <p>作者年龄:{{ author.age }}</p>
    <p>作者性别:{{ author.sex }}</p>
    <p>作者Email:{{ author.email }}</p>
    <hr>
    <h3>作者作品集合:</h3>
    <p>
        {% for book in author.books %}
            <a href="/bookdetail/{{ book.id }}/">《{{ book.title }}》</a>
            {% if not loop.last %}|{% endif %}
        {% endfor %}

    </p>
</body>
</html>

book_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>书籍详情</title>
</head>
<body>
    <h2>《{{ book.title }}》</h2>
    <p>书籍出版时间:{{ book.date }}</p>
    <p>作者:
        <a href="/authordetail/{{ book.my_author.id }}/">{{ book.my_author.name }}</a>
    </p>
    <p>出版社:
        {% for publisher in book.publishers %}
            <a href="/publisherdetail/{{ publisher.id }}/">{{ publisher.name }}</a> |
        {% endfor %}
    </p>

</body>
</html>

book_index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>书籍首页</title>
</head>
<body>
    <h2>书籍首页</h2>
    <a href="/booklist/">查看所有书籍</a>
</body>
</html>

book_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>书籍列表</title>
</head>
<body>
    <h2>书籍列表</h2>
    <ul>
        {% for book in books %}
            <li>
                <a href="/bookdetail/{{ book.id }}/">{{ book.title }}</a>
            </li>
        {% endfor %}
    </ul>
</body>
</html>

publisher_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>出版社详情</title>
</head>
<body>
    <h2>出版社详情</h2>
    <p>出版社名称:{{ publisher.name }}</p>
    <p>出版社地址/城市/省份/国家:{{ publisher.address }}/{{ publisher.city }}/{{ publisher.province }}/{{ publisher.conuntry }}</p>
    <p>出版社网址:{{ publisher.website }}</p>
    <hr>
    <p>出版社出版过的书籍:
        {% for book in publisher.books %}
            <a href="/bookdetail/{{ book.id }}/">《{{ book.title }}》</a>
            {% if not loop.last %}|{% endif %}
        {% endfor %}
    </p>

</body>
</html>

总结:

  • 完成该项目的前提是对Flask模型有足够的认识。
  • 可以看出在Flask模型中,models中主要是进行建立表结构的操作(一对多,多对多)。
  • 在Flask模型中,views主要是进行页面调用和数据库表的增删改查。
  • 在Flask模型中,exts主要就是放插件和拓展。
  • 在Flask模型中,init主要就是初始化。
  • 在Flask模型中,app就是主程序,整个程序从这里启动。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/432224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day15 消息队列

目录 消息队列 消息队列的使用 发送消息 消息的接收 消息队列的控制 消息队列 概念&#xff1a; 消息队列是system V IPC对象的一种&#xff1b; 消息队列有消息队列ID来唯一标识&#xff1b; 消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等&a…

有介质的高斯定理详细证明(电偶极子模型)以及例题讲解

目录 静电场中的电介质 电极化强度的引入 电偶极子模型的计算 电介质极化过程 极化电荷引入 推导 各向同性和线性的电介质 例题 静电场中的电介质 电介质与导体的区别&#xff1a;所有的粒子被束缚在原子核周围&#xff08;限制空间&#xff09; 电介质分为两种 1.无…

OldWang带你了解MySQL(十)

文章目录 &#x1f525;MySQL事务&#x1f525;使用事务&#x1f525;事务的并发问题&#x1f525;MySQL的用户管理&#x1f525;MySQL分页查询 &#x1f525;MySQL事务 事务简介 事务是指作为单个逻辑工作单元执行的一系列操作&#xff0c;要么完全地执行&#xff0c;要么完…

【网络小知识】当我在浏览器url输入文本后的解析流程/http协议对比https协议

当我们在地址栏输入信息之后&#xff0c;我们会得到浏览器给我们一个返回的信息&#xff0c;那么这个信息怎么出来的&#xff1f;且看下文~~~ 目录 ⭐一、浏览器url解析流程⭐二、http协议对比https协议 ⭐一、浏览器url解析流程 在浏览器地址栏输入文本后&#xff0c;比如 “…

window.postMessage()接收不到信息(失效)

问题描述 按照正常的代码逻辑&#xff0c;应该是这个样子&#xff0c;通过iframe打开子窗口&#xff0c;能够正常通信。 // 接收端&#xff08;父窗口&#xff09; window.onmessage function (e) {// 逻辑代码 }// 发送端&#xff08;子窗口&#xff09; window.parent.po…

第一次参加CSDN周赛,这体验很难说···

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 本文章收录于专栏 【CSDN周赛】 本篇文章目录&#x1f30f;前言&#x1f30f;一、勾股数&#x1f338;题目描述&#x1f338;题解&…

Android Activity 了解

前言 : Android 系统的四大组件分别是 1 活动 &#xff08;Activity&#xff09; 2 服务&#xff08;Service&#xff09; 3 广播接收器&#xff08;Broadcast Receiver&#xff09; 4 内容提供器 &#xff08;Content Provider&#xff09; 其中活动是所有安卓应用程序的…

rust闭包(Closure)

闭包(Closure) 闭包在现代化的编程语言中普遍存在。闭包是一种匿名函数&#xff0c;它可以赋值给变量也可以作为参数传递给其它函数&#xff0c;不同于函数的是&#xff0c;它允许捕获调用者作用域中的值。Rust 闭包在形式上借鉴了 Smalltalk 和 Ruby 语言&#xff0c;与函数最…

无聊小知识.04 以下代码会输出什么?

1、前言 今天同事给我看了一段代码&#xff0c;然后这段简单的代码&#xff0c;我却陷入了沉思。 2、代码 String string ""; try {string "123";return string; } finally {string "234"; } 这段代码&#xff0c;string最终是“123”还是…

【SpringSecurity】学习笔记(一)

学习笔记一、SpringSecurity 简介二、创建测试项目2.1、引入依赖2.2、测试三、SpringSecurity基本原理3.1、过滤器链3.1.1、FilterSecurityInterceptor3.1.2、ExceptionTranslationFilter3.1.3、UsernamePasswordAuthenticationFilter3.2、过滤器加载过程3.3、两个重要的接口3.…

看完这篇,保证你学网络安全一帆风顺!

网络安全入门很难吗&#xff1f;总有人抱怨黑客入门太难了&#xff0c;然后仔细了解之后却发现&#xff0c;觉得难是因为看的视频教程都不是配套的&#xff0c;都是这里学一点、那里学一点&#xff0c;脑子里连基本的框架都没有。更过分的是&#xff0c;有的人学了好几个月&…

uniapp - 微信小程序端引入 Echarts 图表及使用详细教程,简单快速的解决方案(拒绝复杂的过程,附带详细的使用示例保姆级教程)

效果图 现在各种平台的文章都太乱了,基本上实测无效。。。 帮你在uniapp开发中,微信小程序平台端使用 echats 图表的详细教程,快速并且简单轻松搞定。 下面是最后的运行结果,随便用的一个图表进行展示,图表更多用法详见文档!

用正则去掉所有HTML标签,保留指定标签

保留单个&#xff0c;如保留img标签&#xff1a;str.replace(/]*>/ig,) 保留多个&#xff0c;如保留strong、em、p、u标签&#xff1a;str.replace(/]*>/ig,) 清除所有标签&#xff0c;就是去掉保留指定标签的部分了&#xff1a;str.replace(/]*>/g, ) replace 正则匹…

(学习日记)2023.4.18

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

java基础——迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类

迭代器&#xff0c;数据结构,List,Set ,TreeSet集合,Collections工具类 第一章 Iterator迭代器 1.1 Iterator接口 在程序开发中&#xff0c;经常需要遍历集合中的所有元素。针对这种需求&#xff0c;JDK专门提供了一个接口java.util.Iterator。 想要遍历Collection集合&…

【Leetcode】最小栈、栈的压入、弹出序列、逆波兰表达式求值

文章目录最小栈栈的压入、弹出序列逆波兰表达式求值最小栈 题目要求是在常数时间内检索到最小的元素的栈&#xff0c;思路是每当栈中存放一个更小的数据时&#xff0c;就将它入栈&#xff0c;相同的值也要入栈。 class MinStack { public:MinStack() {}//对自定义类型&#xf…

梭哈大模型,阿里云成了跟风者?

伴随AI大模型潘多拉魔盒打开&#xff0c;云市场GameChanger已到来。对阿里云这个昔日老大哥而言&#xff0c;从“领先者”变为“跟风者”&#xff0c;是否还有机会去重塑行业规则&#xff1f; 这可能是张勇全面掌舵阿里巴巴7年以来&#xff0c;事关未来最重要的一次“梭哈”。 …

《ChatGPT实用指南》(精编版)重磅发布,全网免费分享,快上车,别掉队

文 / 高扬&#xff08;微信公众号&#xff1a;量子论&#xff09; 据上次3月18号发布的V1.8版&#xff0c;已经过去十天&#xff0c;这期间AI领域发生了很多重大变化。 因此&#xff0c;我们对《ChatGPT实用指南》进行了重大改版&#xff0c;增加了大量实用的操作和详细的讲解&…

【开懂C++】引用与关键字auto

目录 一.引用1.引用的概念2.引用的使用和问题3.引用与指针的比较二.关键字auto 一.引用 1.引用的概念 引用就是给一个已经存在的变量取一个别名&#xff0c;与变量共用一段内存空间。注意引用的类型必须和变量类型相同&#xff0c;来演示下引用如何使用。 #include <iost…

2.1.2事件驱动reactor的原理与实现

先来了解一下epoll select(maxfd, rfds, wfds, efds, timeout);poll(pfds, length, timeout);#include <sys/epoll.h> int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event…