《Flask Web 开发实战(第 2 版)》动态 & 勘误收集

书已收到 :grinning_face:

2 Likes

P10 页
pdm run which python 这个在 windows 11 的 powershell 下运行出错,是否增加个提示,在 windows 下需替换为 pdm run where python ,不知道我的这个算不算勘误,共 greyli 参考。

3 Likes

P24

倒数第四行 编辑排版应该忘了空格了,flaskrun–help 应该是 flask run --help 吧?

1 Like

第51-52页,重定向test_response函数的路由是/response,52页写的是访问/hello

2 Likes

P143 页 第二个代码块

__tablename = 'contacts' 

是否应该是

__tablename__ = 'contacts'

供参考

1 Like

P132 代码清单 4-8
书上:

class MyBaseForm(FlaskForm):
    class Meta:
        locales = ['zh']

可以运行,但是 IDE 里面 Meta下会有红波浪线,提示

“Meta”替代类“FlaskForm”中的同名符号
  “pdm-playground.app.MyBaseForm.Meta”不可分配给“flask_wtf.form.FlaskForm.Meta”
  类型“type[pdm-playground.app.MyBaseForm.Meta]”不可分配给类型“type[flask_wtf.form.FlaskForm.Meta]”PyrightreportIncompatibleVariableOverride
form.py(32, 11): 替代符号

AI 给改成显示继承:

class MyBaseForm(FlaskForm):
    class Meta(FlaskForm.Meta):
        locales = ['zh']

运行效果也是一样。

供参考

1 Like

P160 页 表格 5-7

paginate 第一个参数是 statement 吧?我看写得是 select。
我用 statement 比如:stmt = select(Note) 测试了下,符合我想要的。

供参考

P161 页

书上注释:#按名称获取元素 的意思是?
我试了下,元组不能被用文本切片,是我哪里弄错了么?

>>> notes
[(<Note 1 foo>,), (<Note 2 bar>,), (<Note 3 baz>,)]
>>> notes[0][0]
<Note 1 foo>
>>> notes[0]['Note']
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "lib/sqlalchemy/cyextension/resultproxy.pyx", line 54, in sqlalchemy.cyextension.resultproxy.BaseRow.__getitem__
TypeError: tuple indices must be integers or slices, not str

P164

第二排文字,类似于like(),但必须添加 % 是否是指 使用 like() 才需要添加 % 但是 contains() 不需要?

P164

表格中 endnswith 应该是 endswith 供参考

P168

代码:.values(Note.body=‘My body will be updated.’) 改成 values(body=‘My body will be updated’) 否则报错,供参考
另外,此代码块,最后仍需增加 db.session.commit() 才能提交生效 供参考

>>> stmt = (
...     update(Note)
...     .filter_by(id=2)
...     .values(body='My body will be updated.'))
>>> db.session.execute(stmt)
<sqlalchemy.engine.cursor.CursorResult object at 0x0000028D5C357460>
>>> db.session.commit()
1 Like

页码:176
根据代码清单 5-6 得到

class Author(db.Model):
    __tablename__ = 'author'

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(20))
    phone: Mapped[Optional[str]] = mapped_column(String(11))

    articles: Mapped[list['Article']] = relationship(back_populates='author')

    def __repr__(self):
        return f'<Author {self.id}: {self.name}>'


class Article(db.Model):
    __tablename__ = 'article'

    id: Mapped[int] = mapped_column(primary_key=True)
    title: Mapped[str] = mapped_column(String(50))
    body: Mapped[str] = mapped_column(Text)
    author_id: Mapped[int] = mapped_column(ForeignKey('author.id'))

    author: Mapped['Author']  = relationship(back_populates='articles')

    def __repr__(self):
        return f'<Article {self.id}: {self.title}>'

下文中创建 Author 和 Article 记录不能正确执行,因为没有建立 Author 和 Article 的逻辑关系:

>>> richard = Author(name='Richard')
>>> eggs = Article(title='Eggs', body='blah...')
>>> snake = Article(title='Snake', body='blah...')
>>> db.session.add_all([richard, eggs, snake])
>>> db.session.commit()

报错如下:

```python
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: article.author_id
[SQL: INSERT INTO article (id, author_id, title, body) VALUES (?, ?, ?, ?), (?, ?, ?, ?)]
[parameters: ('b1c35814fbd24672b2d9d207393640a6', None, 'Eggs', 'blah...', '8aa059e967ae43679a697c7868e97d70', None, 'Snake', 'blah...')]
(Background on this error at: https://sqlalche.me/e/20/gkpj)
2 Likes

猜测作者的意图是设置文章的作者可选填写:
author_id: Mapped[Optional[int]] = mapped_column(ForeignKey(‘author.id’), nullable=True)
author: Mapped[Optional[‘Author’]] = relationship(back_populates=‘articles’)

页码:P203
书本上 app.py 示例程序中

SQLITE_PATH = Path(__file__).resolve() / 'db.sqlite'

应该为

SQLITE_PATH = Path(__file__).parent.resolve() / 'db.sqlite'

否则会得到错误的文件路径

>>> db
<SQLAlchemy sqlite:////Users/zhangkaiqiang/PycharmProjects/notebook/app.py/db.sqlite>

导致 db.create_all() 等方法报错

sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) unable to open database file
(Background on this error at: https://sqlalche.me/e/20/e3q8)

GitHub 仓库中给出代码正确。

2 Likes

这里是指参数名是 select

是指用模型类名获取对应元素。这里 notes[0]['Note'] 写错了,应该是 notes[0]._mapping['Note']

P164 这里是出版社校对的时候乱改,导致偏离了原来的意思。我的原始书稿里是这样写的:

第一版就有很多被乱改的地方,而且也没有跟我确认。

确认的几处已经更新到勘误表,感谢反馈!

1 Like

感谢反馈!这里的确有问题,可以把 author_id 设为 nullable(Optional 会自动设置 nullable,不用额外设置):

author_id: Mapped[Optional[int]] = mapped_column(ForeignKey(‘author.id’))

也可以先不提交会话,等设置了双向关系以后再 commit。

第326页 代码清单 9-6 第一行 导入没有换行

from faker import Faker import random
1 Like

第146页 代码清单5-1 获取路径时缺少parent属性:

SQLITE_PATH = Path(__file__).resolve() / 'data.db'

修改:

SQLITE_PATH = Path(__file__).resolve().parent / 'data.db'
1 Like

第46页 最后一段第1行末尾:
为同一个URL规则指定一个视图函数

修改:
为同一个URL规则指定多个视图函数