「Flask实战」鱼书项目实战四

flask鱼书项目实战


jinja2模板

有关jinja2模板的详细可以看我以前的文章
所有静态文件在文末分享,只需要按照文件名替换即可(链接掉了联系我)
替换模板文件后还是不能直接用return render_template('search_result.html', books=books)去直接回显页面的,因为页面上一些业务逻辑还没有实现,所以还需要修改一下代码

修改方案

首先把文件包下原始文件下的statictemplates下的文件替换,然后奖web文件下除了book外五个文件复制到自己目录下的web文件夹下。并且在web目录下的__init__.py把导入的五个蓝图注册上去,然后在web/book.py下添加一个视图函数

@web.route('/book/<isbn>/detail')
def book_detail(isbn):
    pass

最后,在模板文件中找到base.html将71行到79行注释掉,即这一段注释掉

        {% if not current_user.is_authenticated %}
            <div style="float:right">
                <a href="{{ url_for('web.login') }}">登录</a>
                <a style="margin-left: 40px;" href="{{ url_for('web.register') }}">注册</a>
            </div>
        {% else %}
            <a href="{{ url_for('web.personal_center') }}">{{ current_user.nickname }}的鱼书</a>
            <a style="margin-left: 40px;" href="{{ url_for('web.logout') }}">注销</a>
        {% endif %}

这样修改完成后即可去访问http://127.0.0.1:5000/book/search看到效果

消息闪现、SecretyKey与变量作用域

官方文档

Flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。闪现系统使得在一个请求结束的时候记录一个信息,然后在且仅仅在下一个请求中访问这个数据。

1.在视图函数中配置闪现消息

flash("hello,wenfeng", category="success")
flash("hello,jiagndan", category="warning")

2.在html中使用闪现消息

{% set message = get_flashed_messages() %}
{{ message }}

使用set创建变量,这时的变量作用于在整个block

{% with message = get_flashed_messages() %}
{{ message }}
{% endwith %}

使用with关键字,可以随意控制作用域

viewmodel意义的体现filter的应用

在搜索书籍页面里,需要将作者信息,出版社,价格展示在一行,以 / 分割,因为这些信息有可能为空,所以需要对传入的数据进行处理,在html模板里处理不太方便。我们选择将这些数据处理的工作放在viewmodel中,很容易想到if-else但是python提供了更优雅的处理方法filter

# @property注解可以让我们把一个方法当做一个属性来使用
@property
#利用三元表达式 + filter 可以很优雅的进行数据的筛选。
intros = filter(lambda x: True if x else False,[self.author[0], self.publisher[0], self.price[0]])
return ' / '.join(intros)

实现书籍详情页

看到yushu_book.py这里传出去的数据都是一个列表的形式,所以我们可以在接收的时候使用yushu_book[0]这种形式,显然不够好,用户并不知道内部的结构,所以我们应该编写一个对用户体验更良好的接口来返回列表中的第一条数据。

#spider/yushu_book.py

class BookViewModle:
    def __init__(self,book):
        self.title = book['title']
        self.publisher= book['publisher']
        self.pages= book['pages']
        self.price = book['price']
        self.author = '、'.join(book['author'])
        self.summary = book['summary']
        self.isbn = book['isbn']
        self.image= book['image']

    @property
    def intro(self):
        intros = filter(lambda x: True if x else False,[self.author,self.publisher,self.price])

        return ' / '.join(intros)

这样就可以使用yushu.book.first来得到列表中的第一条数据

然后在详情页面调用来得到数据

#web/book.py

@web.route('/book/<isbn>/detail')
def book_detail(isbn):
    yushu_book = YuShuBook()
    #因为isbn编号是唯一的所以通过isbn来确定书籍
    yushu_book.search_by_isbn(isbn)
    book = BookViewModle(yushu_book.first)

    #这里的wishes喝gifts先传入空列表让他正常回显,后面在进行赋值
    return render_template('book_detail.html',book = book,wishes = [],gifts = [])

赠送书籍

models新建三个py文件base.py,gift.py,user.py
base.py用来存放模型中公共的数据,user.py用来存放user模型
gitf.py用来创建user和book的对应关系

#base.py

db = SQLAlchemy()

把实例化抽取,别忘了在sql_book.py中导入

#user.py
from sqlalchemy import Column, Integer, Float, String, Boolean

from app.models.base import db


class User(db.Model):
    id = Column(Integer, primary_key=True)
    nickname = Column(String(24), nullable=False)
    phone_number = Column(String(18), unique=True)
    email = Column(String(50), unique=True, nullable=False)
    confirmed = Column(Boolean, default=False)
    beans = Column(Float, default=0)
    send_counter = Column(Integer, default=0)
    receive_counter = Column(Integer, default=0)
    wx_open_id = Column(String(50))
    wx_name = Column(String(32))
#gitf.py
from app.models.base import db
from sqlalchemy import Column, String, Integer, ForeignKey, Boolean
from sqlalchemy.orm import relationships


class Gift(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    # relationships表示管理关系
    user = relationships('User')
    # ForeignKey定义外键约束
    uid = Column(Integer, ForeignKey('user.id'))
    # 书籍我们记录isbn编号,因为书籍信息是从网络获取的
    isbn = Column(String(15), nullable=True)
    # 是否已经赠送出去
    launched = Column(Boolean, default=False)

gift.py添加软删除

class Gift(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    user = relationships('User')
    uid = Column(Integer, ForeignKey('user.id'))
    isbn = Column(String(15), nullable=True)
    launched = Column(Boolean, default=False
    #添加一条软删除,如果为0则表示被删除
    status = Column(SmallInteger, default=1)

软删除应该在所有数据表中都存在,所以应该把他放在base.py中,让其他表都继承它。

自定义基类模型

像标志位这样的参数,每个表里都有同样的属性,我们应该建立一个基类,来存储这些共有属性

#models/base.py

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column,Integer, SmallInteger

db = SQLAlchemy()


class Base(db.Model):
    create_time = Column('create_time',Integer)
    status = Column(SmallInteger, default=1)

然后修改sql_user.py,sql_book.py,sql_gift.py将它们的继承db.Modle改为继承base就可以完成继承了。

文件包

链接:https://pan.baidu.com/s/18d_vYQlvqi0zJuOtQaMv7Q
提取码:f5zp
复制这段内容后打开百度网盘手机App,操作更方便哦

参与评论