Flask Web开发实战 勘误
为本书包含的错误为你带来的不便感到抱歉!如果你发现了书中的错误,欢迎提交PR更新勘误文件,或是创建Issue反馈,谢谢!
- 最后更新时间:2019/2/2
- 因为电子书尺寸不固定,会产生不同的页数,这里的勘误页码为纸书页码,电子书可以根据章节和位置来定位错误内容,或是等待下一次重印推送更新。
第 1 次印刷版本勘误表
此处的勘误表为第 1 版第 1 次印刷版本。第 1 版第 2 次印刷版本的勘误表请访问 1-2 勘误表查看。印刷版次可以在前言前一页查看。电子书与最新版本保持一致,如果没有更新,可以联系客服手动更新。
位置 | 错误 | 正确 | 备注/时间 |
---|---|---|---|
1.2.2.2 P13 代码清单1-3下第2段第2行 | http://helloflask.com/hello/Grey | http://helloflask.com/greet/Grey | 笔误 |
1.7 P23 第2个代码块下第1行 | url_for('say_hello', name='Jack') |
url_for('greet', name='Jack') |
笔误 |
2.2 P30 | 请求报文示例表格 | URL /hello 改为 http://helloflask.com/hello?name=Grey | |
2.2 P30 | 请求报文示例表格 | 去掉主体一栏的内容 | |
2.2 P30 | 请求报文示例表格下方正文 | 如果 URL 中包含查询字符串,或是提交了表单,那么报文主体将会是查询字符串和表单数据。 | 如果提交了表单,那么报文主体将会是表单数据(查询字符串直接通过 URL 传递)。 |
2.2 P31 命令行输出 | /hello | /hello?name=Grey | 19.2.2 |
2.2.1 P31 表2-3左侧下面的两行 | POST对应的说明列原文为“传输数据”,修改为“创建或更新资源”;PUT对应的说明列原文为“传输文件”,修改为“创建或替换资源” | 改进 18.11.18 | |
2.2.3.3 P36 表2-6后第1个代码块 | 'goback/<int:year>' |
'/goback/<int:year>' |
笔误。 18.9.28 |
2.3.1 P40 第3个代码块 | {'Location', 'http://www.example.com'} |
{'Location': 'http://www.example.com'} |
笔误。返回值中字典里的符号出错 |
2.3.2 P44 HTML小节的最后1行 | HTTP | HTML | 笔误 |
2.3.2.4 P46 倒数第3个代码块 | return jsonify({name: 'Grey Li', gender: 'male'}) |
return jsonify({'name': 'Grey Li', 'gender': 'male'}) |
笔误。字典键加引号 18.10.18 |
2.2.3 P48 图2-11 | 图中的响应状态码应该为 302 Found | 文图不对应 18.10.18 | |
2.3.4.2 P50 代码清单2-5下第1段第3行 | logged-in cookie | logged_in cookie | 排版错误 18.11.8 |
2.3.4.2 P51 图2-12后第1个代码块 | 第9行及以下均应向左缩进4个空格 | 排版错误 18.10.18 | |
2.3.4.2 P52 图2-13后第1段第2行 | logged-in | logged_in | 排版错误 18.11.8 |
2.3.4.2 P52 代码清单2-6下第2段第2行 | logged-in | logged_in | 排版错误 18.11.8 |
2.5.4.1.(2) P67 “攻击示例”小节第3段文字第2行 | 设为 “';drop table users; --” | 设为 “';drop table students; --” | 笔误 18.11.2 |
4.2.3 P110 代码清单4-2最后1行 | 'login.html' |
'basic.html' |
笔误 18.9.28 |
4.3.1 P112 第1个代码块后第1行 | 3000 | 2000 | 笔误,不同的浏览器对于URL有不同的长度限制,此处长度为“最佳实践” |
4.3.1 P113 代码清单4-5第1行 | '/' |
'/basic' |
笔误 18.10.18 |
4.3.1 P115 第 2 小节的代码块第 5 行 | Length(8, 128) |
Length(6, 128) |
前后不一致(1-3 重印时需要反过来调整另外 3 处),18.12.28 |
4.4.4.3.(3)第6个代码块下正文第2行 P127第2个代码块下正文第2行 | 这个uploads视图 | 这个get_file视图 | |
4.4.4.4 P128 代码清单4-16 | “检查文件类型”注释下第一行多余缩进4格 | 笔误 18.10.18 | |
5 P139 第 1 个代码块 | $ flask run 上面添加一行 $ flask initdb # 初始化数据库,后面会详细介绍 |
疏漏 19.1.5 | |
5.4.1.1 P147 ”Create“小节第1个代码块第4行 | 'DON'T BELIEVE……' |
'DON\'T BELIEVE……' |
代码错误,漏掉转义符号 |
5.4.1.2 P150 表5-7下的第1个代码块 | Note.body='SHAVE' |
Note.body == 'SHAVE' |
代码错误,少了1个等号 18.9.22 |
5.4.2 P153 代码清单 5-5 | 删掉第 3 行,最后一行删除括号中的, form=form |
代码未更新 18.12.24 | |
5.4.2 P155 代码清单 5-8 第 3 行 | DeleteForm() |
DeleteNoteForm() |
代码未更新 18.12.24 |
5.5.2.3 P160 ”建立关系“小节第1个代码块 | 第2行插入ham.author_id = 1 |
省略步骤,可加可不加 18.9.22 | |
5.5.2.4 P162 代码清单5-11第8行 | title = |
name = |
笔误 18.9.26 |
5.5.2.4 P163 ”建立双向关系“小节第3个代码块第6行 | it.writer = writer |
it.writer = king |
笔误 18.9.26 |
5.5.3 P164 代码清单5-13上面 | 都定义在“多”这一侧,即City类中 | 都定义在“多”这一侧,即Citizen类中 | 笔误 |
5.5.4 P165 代码清单5-14后面的代码块第6行 | - | 第6行>>> china.capital = beijing 移动到第3行 |
笔误 |
5.5.4 P165 代码清单5-14后面的代码块第8行 | <Capital 1> |
<Capital u'Beijing'> |
笔误 |
5.5.4 P166 代码清单5-14后面的代码块第10行,166页第2行 | u'China' |
<Country u'China'> |
笔误 |
5.5.4 P166 代码清单5-14后面的代码块第11行,166页第3行 | name'Tokyo' |
name='Tokyo' |
笔误 18.9.26 |
5.7.1.2 P174 ”delete-orphan“小节上面第1个代码块第1行 | Post.quer2y.get(2) |
Post.query.get(2) |
审校错误 |
5.7.2 P176 代码清单5-18下第1行 | targe | target | 笔误 18.9.28 |
5.7.2 P177 最后1个代码块上面 | 参数name | 参数named | 笔误 18.9.28 |
5.7.2 P177 最后1段提示文字 | 监听函数时, | 监听函数。这时 | 编辑瞎改稿子 18.9.28 |
5.7.2 全章节多处 | listen_for | listens_for | 笔误 18.9.28 |
6.1.1 P181 代码清单6-1 | 第9-13行末尾漏掉分割参数的逗号 | 笔误 18.10.27 | |
7.3.2 P208 第1个代码块第6行 | render_form(form),action=request.full_path |
render_form(form, action=request.full_path) |
审校错误,右侧关闭括号位置出错 |
7.3.2 P208 表7-2上面段落的最后一句话 | quick_form() | render_form() | 笔误。历史遗留问题 18.9.28 |
7.4.3 P213 最后 1 个附注段落 | bootstrap.bundle.min.css | bootstrap.bundle.min.js | 笔误 18.12.5 |
8.1.3 P229、P231 代码清单8-2、8-4 | 单个蓝本变量名称均应为foo_bp形式,比如admin应为admin_bp | 笔误 18.9.24 | |
8.2.1.1.(4) P235 代码清单8-7后面第1个代码块第3行 | db.relationship('Comment', backref='post', cascade='all') |
db.relationship('Comment', back_populates='post', cascade='all, delete-orphan') |
笔误 |
8.2.3 P247 代码清单8-19第2行 | from wtforms |
from wtforms.validators |
笔误 18.10.27 |
8.3.1 P252 第1个代码块最后1行 | 'index.html' |
'blog/index.html' |
笔误 18.10.06 |
8.3.1 P252 代码清单8-24文件路径 | templates/index.html | templates/blog/index.html | 笔误 18.10.06 |
8.3.5 P263 第1个代码块第6行 | Comment.query.with_parent(post) |
Comment.query.with_parent(post).filter_by(reviewed=True) |
笔误 18.9.26 |
8.3.5 P264 代码清单 8-29 倒数第11行 | Reply</a> |
Reply</a></div> |
笔误 18.12.6 |
8.3.5 P265 图 8-8 上的代码块第2行 | {{ comment.replied.author.name }} |
{{ comment.replied.author }} |
笔误 18.12.6 |
8.3.7 P267 代清清单8-31第4行 | comment.photo_id |
comment.post_id |
笔误 18.9.26 |
8.3.7 P267 代清清单8-31下方正文第2段最后一行的URL中 | photo | post | 笔误 18.9.26 |
8.3.7 P268 第1行 | photo | show_post | 笔误 18.12.6 |
8.4.1 P272 第1个代码块最后1行 | >>> False |
>>> True |
笔误 18.10.27 |
8.4.1 P273 纸书该页第 2 个代码块,电子书 8.4.2 上面倒数第 2 个代码块。第 5、7 行 | check_password |
validate_password |
笔误 18.12.6 |
8.5 P275 “8.5”小节下第2个代码块第2行 | LoginManager(app) |
LoginManager() |
代码错误 18.12.23 |
8.5.3 P278 代码清单8-37代码块第1行 | from flask_login import logout_user |
from flask_login import logout_user, login_required |
完善导入 18.12.6 |
8.6 P282 代清清单8-38第4行 | '400.html' |
'errors/400.html' |
笔误 18.10.27 |
8.7.1 P285 代码清单8-40下的正文第1行 | manage_category.html | manage_post.html | 笔误 18.10.27 |
8.7.1.2 P288 代码清单8-42代码块倒数第2行 | .show_post |
blog.show_post |
笔误 18.12.6 |
8.7.1.3 P290 第1个代码块倒数第5行 | .show_post |
blog.show_post |
笔误 18.12.6 |
8.7.2 P292 代码清单8-44代码块倒数第1行 | .show_post |
blog.show_post |
笔误 18.12.6 |
8.7.2.2 P294 代码清单8-45代码块下正文第1行 | Ture |
True |
笔误 18.12.6 |
9.1.1 P302 9.1.2 标题上面的代码块 | bluelog |
myapp |
笔误 18.12.6 |
9.3.2.2 P314 代码清单9-6代码块最后1行 | url_for('.resend_confirmation') |
url_for('.resend_confirm_email') |
笔误 18.12.12 |
9.3.3 P315 代码清单9-8下的正文第2段第2行(纸书该页最后1行) | auth.resend_confirmation |
auth.resend_confirm_email |
笔误 18.11.5 |
9.5.3 P334 9.6 小节上面的代码块最后一行模板字符串 | home/upload.html |
main/upload.html |
遗留代码未更新 18.12.17 |
9.5.3 P334 代码清单9-19后面的代码块倒数第二行 | photo.save() |
db.session.add(photo) 换行 db.session.commit() |
遗留代码未更新 18.10.27 |
9.8.3 P363 代码清单9-45代码块倒数第6行 | {% if collections %} |
{% if collects %} |
笔误 18.12.10 |
9.9.4 P371 代码清单9-53的路径 | albumy/templates/profile_popup.html | albumy/templates/main/profile_popup.html | 笔误 18.12.21 |
9.9.4 P375 代码清单 9-56 下面的代码块第二行 | id="followers-count" | id="followers-count-{{ user.id }}" | 笔误 18.12.21 |
9.11.2 P388 最后一行 | 渲染avatar.html模板 | 渲染change_avatar.html模板 | 笔误 18.12.10 |
9.11.2 P389 第一个代码块下正文第1行 | avatar.html模板继承自settings.html模板 | change_avatar.html模板继承自settings/base.html模板 | 笔误 18.12.10 |
9.11.2 P389 代码清单9-71代码块第1行 | {% extends 'user/settings.html' %} |
{% extends 'user/settings/base.html' %} |
笔误 18.12.10 |
9.11.6 P397 代码清单9-79代码块倒数第5行 | current_user |
current_user._get_current_object() |
笔误 18.12.10 |
9.11 P385 代码清单9-66倒数第9行 | {{ render_nav_item('user.notification_setting', 'Notification and Privacy') }} |
{{ render_nav_item('user.notification_setting', 'Notification') }} {{ render_nav_item('user.privacy_setting', 'Privacy') }} |
代码与实际项目不符 18.12.24 |
9.11.2 P389 代码清单9-71倒数第4行 | {{ render_form(crop_form) }} |
{{ render_form(crop_form, action=url_for('.crop_avatar')) }} |
笔误 18.12.24 |
9.14.3 P412 代码清单9-90 | 缺少validate_username()方法的定义 18.12.24 | ||
10.1.1 P420 第 2 小节第一个代码块第 7 行 | {{ url_for('todo.clear_item') }}; |
{{ url_for('todo.clear_items') }}; |
笔误 18.12.27 |
10.1.4 P425 第一个代码块第 6 行 | jsonify(message='Invalid item body.'), 400 |
return jsonify(message='Invalid item body.'), 400 |
笔误 19.1.20 |
10.3.3 P447 第 1 小节/该页最后一个代码块 | ... import api |
... import api_v1 |
笔误 18.12.28 |
10.3.3 P447 第 1 小节/该页最后一个代码块 | csrf.exempt(api) |
csrf.exempt(api_v1) |
笔误 18.12.28 |
10.3.3 P453 代码清单10-13第一行中的methods参数 | methods=['GET', 'POST'] |
methods=['GET'] |
与原定的方法不一致 18.12.28 |
10.3.3 P453 代码清单10-13第二行中的第一个参数 | '/token' |
'/oauth/token' |
与实际项目不一致 18.12.28 |
10.3.3 P453 代码清单10-13第二行中的methods参数 | methods=['GET'] |
methods=['POST'] |
与实际项目不一致 18.12.28 |
10.3.5 P462 代码清单10-20倒数第4行 | item.author, |
item.author.username, |
笔误 18.12.28 |
10.3.6.3 P468 ”处理错误响应“小节第1行 | app.error_handler | app.errorhandler | 笔误 |
11.3.2 P483 代码清单11-4倒数第2行 | 花括号"}"后添加一个逗号"," | 笔误 18.12.28 | |
11.3.2 P484 代码清单11-5第2行 | $('message') |
$('.messages') |
笔误 18.12.28 |
11.4.1 P491 该节最后一段正文的第1行 | views包 | blueprints包 | 笔误 18.12.29 |
11.4.3 P498 附注段落下方正文第2行 | provide_name | provider_name | 笔误 18.12.29 |
11.4.3.5 P503 代码清单11-11中多处 | get['XXX'] |
get('XXX') |
审校错误 |
11.4.3.5 P503 最后一个代码块 | access_token = resp.get('access_token') |
access_token = response.get('access_token') |
笔误 18.12.29 |
11.4.3.6 P505 提示段落上方的代码块 | @oauth_bp.route(...) |
@auth_bp.route(...) |
笔误 18.12.29 |
11.4.4 P506 第二个代码块 | 所有resp 改为 response | 笔误 18.12.29 | |
11.4.4 P506 第二个代码块 | 增加 if response is not None:... else:...语句,具体参考源码 | 笔误 18.12.29 | |
11.5.1 P508 代码清单11-12 | '_messages.html' |
'chat/_messages.html' |
笔误 18.12.29 |
11.5.1 P509 代码清单11-13第5行 | position === 0&& socket.nsp! == '/anonymous' |
position === 0 && socket.nsp !== '/anonymous' |
审校错误,空格错误 18.12.29 |
11.5.1 P510 代码清单11-13倒数第6行 | toast('No more messages.'); |
alert('No more messages.'); |
此项目中未定义toast函数 18.12.29 |
11.5.3 P513~P514 513页7处,514页8处 | 所有的 Pyments 改为 Pygments,pyments 改为 pygments | 笔误 18.11.18 | |
11.5.4 P516 代码清单11-15第3行 | 'message' |
'new message' |
笔误 18.12.29 |
11.5.4 P516 代码清单11-15第6行 | document.title = '(' + message_count + ') ' + document.title; |
document.title = '(' + message_count + ') ' + 'CatChat'; |
消息数量会随着事件多次发生而不断追加在原标题前 18.12.29 |
11.5.5 P517 代码清单11-17第6行 | data.name |
data.nickname |
笔误 18.12.30 |
11.5.5 P517 代码清单11-17第7行 | icon: ... |
icon: data.gravatar |
笔误 18.12.30 |
11.5.5 P518 最后1个代码块第5行 | '_message.html' |
'chat/_message.html' |
笔误 18.12.30 |
11.5.5 P518 最后1个代码块第6行 | message_body |
html_message |
笔误 18.12.30 |
12.3.1 P526 代码清单12-1 | setUp方法最后面追加一行代码self.client = app.test_client() |
代码缺失 19.01.05 | |
12.3.2 P527 提示段落下方的正文第3行 | assertEqual() | assertTrue() | 笔误 19.01.05 |
12.3.2 P527 代码清单12-3 test_404_page方法的注释 | # 测试 400 错误页面 | # 测试 404 错误页面 | 笔误 19.01.05 |
12.3.3 P534 代码清单12-6最后1个导入语句 | from bluelog.models import User |
from bluelog.models import Admin |
笔误 19.01.06 |
13.1.2 P550 代码清单13-1 | @app.after_app_request |
@app.after_request |
笔误 19.01.06 |
13.1.2 P550 代码清单13-1 | 两处current_app改为app | 笔误 19.01.06 | |
13.3 P557 命令行命令 | $ cd cache |
$ cd assets |
笔误 19.01.06 |
14.3.4.1 P569 代码清单14-1上方正文 | register_logger() |
register_logging() |
与实际源码不符 19.01.21 |
14.3.4.1 P569 代码清单14-1 | register_logger() |
register_logging(app) |
与实际源码不符 19.01.21 |
14.3.4.1 P569 代码清单14-1 | RotatingFileHandler的第一个参数 | os.path.join(basedir, 'logs/bluelog.log') |
与实际源码不符 19.01.21 |
14.3.4.2 P570 代码块 | register_logger() |
register_logging(app) |
与实际源码不符 19.01.21 |
14.3.4.3 P571 代码清单14-2 | register_logger() |
register_logging(app) |
与实际源码不符 19.01.21 |
14.3.4.3 P571 代码清单14-3 | register_logger() |
register_logging(app) |
与实际源码不符 19.01.21 |
14.3.4.3 P571 代码清单14-3 | 5处os.getenv() |
app.config[] |
与实际源码不符 19.01.21 |
14.4.3.1 P576 提示段落第二行 | C/Users/Administrator/.ssh | C:\Users\Administrator.ssh | 错误 19.01.21 |
14.4.7 P584 倒数第2个代码块上方段落第5行 | 放在/etc/supervisord.conf路径下 | 放在/etc/supervisor/conf.d路径下 | 笔误 18.11.28 |
15.5 P611 正文第5行 | 在模板中提供load()方法资源。 | 在模板中提供load()方法加载静态资源。 | 句子不完整 19.01.21 |
15.5.1 P612 页面中部代码块 | def load(css_url=None, js_url=None): |
def load(css_url=None, js_url=None, serve_local=False): |
与实际源码不符 19.01.21 |
15.5.1 P612 页面中部代码块 | if current_app.config['SHARE_SERVE_LOCAL']: |
if serve_local or current_app.config['SHARE_SERVE_LOCAL'] |
与实际源码不符 19.01.21 |
15.5.1 P612 页面中部代码块最后1行中的filename参数 | filename='js/share.min.js' |
filename='js/social-share.min.js' |
笔误 19.01.21 |
15.6.1 P614 代码清单15-8中Share类的init_app方法中的blueprint | Blueprint缺少static_folder和static_url_path参数 | 见代码清单15-5或项目源码 | 笔误 19.01.21 |
15.6.1 P614 代码清单15-8中Share类的init_app方法 | 没有将扩展添加到模板上下文 | 添加代码app.jinja_env.globals['share'] = self |
代码缺少 19.01.21 |
15.6.1 P614 代码清单15-8中Share类的init_app方法最后1行第2个参数 | True | False | 与实际源码不符 19.01.21 |
15.6.1 P615 代码清单15-7和代码清单15-8中Share类的create方法参数 | addition_class=None |
addition_class='' |
与实际项目不符 19.01.21 |
15.7.3 P625 最后1个代码块的第2行 | git push origm |
git push origin |
审校错误。另外,这一行下面的Github应为GitHub |
16.2.4 P639 最后1个段落的第2行 | 在不基于线程、greenlet或单进程实现的并发服务器上 | 在不基于线程、Greenlet 或进程实现并发的服务器上 | 笔误 18.12.31 |
16.4.2 P649 最后1行 | Flask.route()是Flask类的类方法 | Flask.route()是Flask类的实例方法 | 笔误 19.1.1 |
16.4.2.1 P650 最后第2段正文第1行 | view_function | view_functions | 笔误 19.01.21 |
16.4.2.2 P653 代码清单16-15中的注释 | 出于 | 处于 | 笔误 19.01.21 |
16.4.3.2 P659 第1段第3行 | 并将数据的字典名称设为'stack'。 | 并将储存上下文对象的列表名称设为'stack' | 笔误 19.1.4 |
16.5 P680 附注第2行 | Pocco风格指南 | Pocoo风格指南 | 笔误 19.01.21 |
还有一些不重要的勘误没有在这里列出,详情访问勘误源码查看。