中企动力 > 头条 > python中flask

网站性能检测评分

注:本网站页面html检测工具扫描网站中存在的基本问题,仅供参考。

python中flask

学习python flask之九:如何debug以及解决之前代码中的bug 互联网视频课程

img

淳于芸

关注

处理bug的最好方式是亲自经历一次。在之前完成的应用中有一个bug。怎么触发这个bug呢?首先确保你的应用中注册了至少两个用户,登录其中一个用户,打开profile页并点击编辑链接。在编辑profile页面中,username改为另一个已经注册的用户,然后bug出现了。

此时建议打开debug功能, export FLASK_DEBUG=1,再触发一次该bug,就能看到如下的debug信息。

出现这个bug的原因是在把username写入数据库时,写入了一个已经存在的用户名,而用户名定义成唯一,因此出现错误。

回想一下,RegistrationForm已经验证了username,但是编辑表单的需求有点不同。注册中,需要确保用户输入的用户名在数据库中不存在。编辑profile时也需要做相应的检查。

解决这个问题的方法是添加对username的检查。

由于EditProfileForm的构造函数增加了参数,因此创建它的对象时需要添加参数。

form = EditProfileForm(current_user.username)

然后在验证参数时显式的调用form.validate_username函数。

[漫哥]python-flask(二)sqlite数据库操作实现简单留言实例 推广视频课程

img

车水马龙01

关注

实例描述: 用户输入姓名电话邮箱并留言

设计:

1.输入信息,通过POST上传,确认数据执行sql insert近数据库,返回上次结果

2.查看上次信息,执行sql Select 查询数据,返回并遍历数据

环境: sqlite3,py2

目录结构:

Projects_mange_1

│ Projects_1.py

│ user_db.db

│ user_db.sql

└─templates

index.html

list.html

数据库设计:

表名user_info

数据:{'uid':"uuid",'name':"user name",'mail':"e-mail",'phone':"phone number",'word':"word",'time_at':"at time"}

user_db.sql

手动创建数据库

到路径里 sqlite3 user_db.db

user_db.sql

源码:

Index.html

一个表单,上传数据

List.html

显示所有数据

main:

喜欢的朋友关注一下漫哥,漫哥会陆续发表更多Flask实例

作者:漫哥

Python牛人利用Flask框架五分钟开发restful Web ApI!涨见识了! 推广视频课程

img

路望断

关注

Flask使用Python编写,多个良好的部署选项使用简单灵活。它是一个年轻充满活力的微框架,有着许多拥护者,文档齐全,社区活跃度高。Flask底层使用werkzeug来做路由分发,代码写起来十分简单!学好FLASK框架是一件很有趣的事情,而且它能够给你带的价值也非常大,它现在发展的特别迅速。

请求调度资源:

要求获取参数:

请求方法( HTTP谓词):

请求数据和标题:

答复:

状态代码和错误:

批准:

简单调试和日志记录:

Python-Flask系列(第十二篇:你说不全了解的表单) 企业视频课程

img

Ren

关注

在上篇文章中,我们简单介绍了Flask中的表单对应的扩展模块Flask-WTF的安装和使用具体方法。

在对表单的引入,创建以及使用有了初步的了解之后,今天我们来详细介绍一下Flask-WTF具体包括的内容,来帮你查漏补缺。

1.WTForm 支持的HTML标准字段

类型

功能含义

StringField

文本字段

TextAreaField

多行文本字段

PasswordField

密码文本字段

HiddenField

隐藏文本字段

DateField

文本字段,格式为datetime.date格式

DateTimeField

文本字段,格式为datetime.datetime格式

IntegerField

文本字段,值类型为整数

DecimalField

文本字段,值为decimal.Decimal

FloatField

文本字段,值类型为浮点数

BooleanField

复选框,值为True或False

RadioField

一组单选框

SelectField

下拉列表

SelectMultipleField

下拉列表,可以多选

FileField

文件上传字段

SubmitField

表单提交按钮

FormField

把表单作为字段嵌入到另一个表单

FieldList

一组指定类型的字段

2.WTForm 支持的验证函数

验证函数

功能说明

Email

验证电子邮件地址

EqualTo

比较两个字段的值;一般用于要求输入两次密码的情况

IPAddress

验证IPv4网络地址

Length

验证输入字符串的长度

NumberRange

验证输入的值在数字范围内

Optional

无输入值时跳过其他验证函数

Required

确保字段中有数据

Regexp

使用正则表达式验证输入值

URL

验证URL

AnyOf

确保输入值在可选列表中

NoneOf

确保输入值不在可选列表中

这样,我们就详细了解了WTForm提供的所有的可用字段以及字段可以附加的验证函数的具体内容。

虽然表单的类型多样,当总结起来都是常用情形:输入文本、密码,上传文件图像,表格内嵌,重置密码,时间选择框等等,每一个场景基本都有对应的响应的字段,而每个字段我们都会在实际应用中选择对应的验证函数以确保输入数据的安全性和正确性。

今天的内容我们详细介绍的表单的字段和验证函数,是在前端模板开发中用到的常用数据,需要熟记于心。

相信你能够多多复习,深刻记忆。

今天的内容到此结束,每天进步一点点,累月成就大辉煌,让我们共同进步吧。

积跬千里,化茧成蝶

Learn Python 3:Flask Web开发小记,大神超详细总结,三天学会 互联网视频课程

img

Ethel

关注

最近看了Flask Web开发:基于Python的Web应用开发实战,书中详细介绍了Web程序的开发、测试、部署过程,值得一读!我在书中例子的基础上做了些更改,实现了一个简单的个人博客:NiceBlog,仅作为个人学习,还有许多不足的地方待完善,这里做一些简单的记录,方便以后查阅

大家如果喜欢我们文章,可以在小编的学习平台学习,可以在评论区获取

也希望看到积极留言

一、功能

1、对于普通用户,主要有如下功能:

注册、登录、重置密码(邮箱验证)文章列表、详情评论喜欢

2、对于管理员,除了有普通用户的功能,主要有如下功能:

写文章(Markdown编辑)用户权限管理(管理喜欢、评论的权限)评论管理(删除、屏蔽)

3、为移动端提供相关api接口

二、项目结构

遵循了书中多文件Flask程序的基本结构,下边是NiceBlog的项目结构:|-NiceBlog|-app/ 主目录 |-api/ 为移动端提供接口的蓝本 |-auth/ 权限认证的蓝本 |-main/ 主体功能的蓝本 |-manage/ 管理相关功能的蓝本 |-static/ 静态资源目录(icon、js、css) |-templates/ html模板目录 |-__init__.py 初始化项目的工厂函数 |-decorators.py 自定义的装饰器 |-email.py 发送邮件功能 |-excepitions.py 自定义异常处理 |-models.py 数据模型 |-migrations/ 数据库迁移脚本目录 |-nb_env/ 虚拟环境 |-tests/ 单元测试目录 |-config.py 配置文件 |-manage.py 启动程序以及其他的程序任务 |-requirements.txt 项目的依赖包列表

三、实现

1、工厂函数

一个简单的Flask Web程序可以写在单文件中,

test.py

app = Flask(__name__)# 定义的路由@app.route('/')def index():return '

Hello World!

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

但是执行程序时,由于在全局作用域创建导致无法动态修改配置,也导致了单元测试时无法在不同配置环境运行程序。所以可以把程序的创建转移到可显示调用的工厂函数中,也就是前边项目结构中的

__init__.py

,在工厂函数中导入需要的Flask扩展:

def create_app(config_name):app = Flask(__name__) # 导致指定的配置对象 app.config.from_object(config[config_name]) # 调用config.py的init_app() config[config_name].init_app(app) # 初始化扩展 bootstrap.init_app(app) mail.init_app(app) moment.init_app(app) db.init_app(app) login_manager.init_app(app) pagedown.init_app(app) return app

2、蓝本

新的问题来了,使用工厂函数后,程序在运行时创建,而不是在全局作用域,必须等到执行

create_app()

后才能使用

@app.route()

装饰器,这时就要使用蓝本了,在蓝本中也可以定义路由,但是定义的路由处于休眠状态直到蓝本注册到程序后在成为程序一部分,例如main蓝本的目录结构如下:|-NiceBlog|-app/ 主目录 |-main/ 主体功能的蓝本 |-__init__.py 创建蓝本 |-errors.py 蓝本的错误处理 |-forms.py 蓝本的表单 |-views.py 蓝本的路由

首先看一下

__init__.py

# 两个参数分别指定蓝本的名字、蓝本所在的包或模块(使用 __name__即可)main = Blueprint('main', __name__)# 导入路由模块、错误处理模块,将其和蓝本关联起来# 在蓝本的末尾导入在两个模块里还要导入蓝本,防止循环导入依赖from app.main import views, errors

2.1、表单

forms.py

是当前蓝本中的表单,项目中使用了

FlaskForm

,可以方便的完成表单校验,例如创建、编辑文章的表单:

class BlogForm(FlaskForm):title = StringField('请输入文章标题', validators=[DataRequired(), Length(1, 128)]) labels = StringField('文章标签(标签之间用空格隔开)', validators=[DataRequired()]) summary = TextAreaField('文章概要', validators=[DataRequired()]) content = TextAreaField('文章内容', validators=[DataRequired()]) preview = TextAreaField('文章预览', validators=[DataRequired()]) publish = SubmitField('发布') save = SubmitField('保存')

2.2、路由

views.py

就是在蓝本中定义的路由,例如主页的路由:

@main.route('/create-blog', methods=['GET', 'POST'])@admin_requireddef create_blog():""" 写新文章 """ form = BlogForm() if form.validate_on_submit(): blog = None if form.publish.data: # 发布 elif form.save.data: # 保存草稿 return redirect(url_for('main.index')) return render_template('markdown_editor.html', form=form, type='create')

注意装饰器为当前蓝本的名字

main

,而不是之前的

app

create_blog()

称为视图函数,一个路由保存了URL到视图函数的映射关系。

redirect(url_for('main.index'))

代表重定向到主页,

url_for()

的参数为要跳转到的URL对应的视图函数名,但需要加上视图函数所在的蓝本名,即

main.index

render_template()

是Flask提供的函数,把

Jinja2

模板引擎集成到了程序中,第一个参数是模板名称对应一个html文件,即执行该视图函数后最终要渲染的页面,后边的参数为传递给模板的参数。

2.3、错误处理

errors.py

是蓝本中的错误处理程序,例如:

@main.app_errorhandler(404)def page_not_found(e):if request.url.find('api') != -1: return jsonify({'error': '请求的资源不存在', 'code': '404', 'data': ''}) return render_template('error/404.html'), 404

如果使用

@main.errorhandler

装饰器只有当前蓝本的错误才能触发,为了使其他错误也能触发所以使用了

@main.app_errorhandler

装饰器

2.4、注册蓝本

其它蓝本的定义也类似,最后需要在工厂函数中重注册蓝本,例如:

def create_app(config_name):# ...... # 注册main蓝本 from app.main import main as main_blueprint app.register_blueprint(main_blueprint) # 注册auth蓝本 from app.auth import auth as auth_blueprint # 使用url_prefix注册后,蓝本中定义的所有路由都会加上指定前缀,/login --> /auth/login app.register_blueprint(auth_blueprint, url_prefix='/auth') return app

3、前端

3.1、Jinja2

Flask使用

Jinja2

作为模板引擎,模板是一个包含响应文本的HTML文件,其中包含只有在请求的上下文才知道的动态占位变量。默认情况下,模板保存在

templates

目录。

Jinja2

模板中

{{ 变量名 }}

代表一个变量(注意变量名两边有一个空格,可以识别任意类型的变量),从渲染模板时使用的数据中获取。如果变量的值是HTML,由于转义的原因导致浏览器不能正常显示HTML代码,所以需要使用

safe

过滤器,例如文章详情的HTML显示就需要这样处理,过滤器写在变量名后用竖线隔开

{{ 变量名|过滤器名 }}

Jinja2

中用

{% 控制语句 %}

代表控制结构来改变模板的渲染流程,例如:

# 条件控制{% if xxx %}

Android

{% else %}

iOS

{% endif %}

# for循环{% for x in xs %}

{{ x }}

{% endfor %}

# 导入{% import 'xxx.html' %}

# 包含{% include 'xxx.html' %}

导入、包含的目的都是为了复用,还可以通过继承实现复用,类似于类的继承:

# 继承{% extends "base.html" %}

通过继承,模板中重复的代码都可以写在父模板里,例如导航条和页面底部footer就可以放在父模板里。

3.2、Bootstrap

前端使用了Bootstrap框架,它提供了良好的CSS规范,可以帮助我们更好的美化界面,具体的可参考:https://v3.bootcss/,要在项目中集成它可以使用Flask的

Flask-Bootstrap

扩展,直接在PyCharm安装,并在工厂函数中初始化,还要让项目的父模板继承Bootstrap的基类模板:

# common_base.html{% extends "bootstrap/base.html" %}

Bootstrap的基类模板

base.html

提供了一个网页框架,包含了Bootstrap中的所有CSS和JS文件。除此之外基类模板还定义了许多可在其子类模板中重定义的块,使用格式如下:

{% block 块名称 %}{% endblock %}

常用的块如下:

块名称

含义

head标签中的内容

title

标签中的内容

body标签中的内容

stylescss样式单的定义

navbar自定义的导航条

content自定义的页面内容

page_content定义content在内部

scriptsJS声明,一般在模板尾部

注意如在子模板在模板已有的块中添加新内容,需要使用

super()

函数:

{% block scripts %}{{ super() }} {% endblock %}

3.3、Flask-WTF

在2.1中我们已经看到了用

Flask-WTF

定义表单的方式,即自定义的表单类继承

FlaskForm

类,并添加需要的类变量,

Flask-WTF

定义了许多标准字段可以被渲染成指定的表单类HTML标签,例如:

字段名

对应的H5标签

StringField文本框

TextAreaField多行文本框

PasswordField密码输入框

BooleanField复选框

SubmitField表单提交按钮

同时

Flask-WTF

还提供了许多常用的表单校验函数,例如:

Email()

EqualTo()

DataRequired()

Length()

等等,当点击提交按钮时,会自动校验表单是否满足预定义的条件。

在2.2中,我们通过参数把表单类的实例同步

form

参数传入模板:

render_template('markdown_editor.html', form=form, type='create')

在模板中可以通过如下方式生表单(只保留了部分核心代码):

{{ form.hidden_tag() }} {{ form.title(id="title", class="form-control editor-blog-title", placeholder=form.title.label.text) }} {{ form.labels(class="form-control editor-blog-area", placeholder=form.labels.label.text) }} {{ form.summary(class="form-control editor-blog-area", placeholder=form.summary.label.text, rows=3) }} {{ form.publish(class="btn btn-info") }} {{ form.save(class="btn btn-success") }}

这样的好处是我们能自定义表单的样式等等,但是工作量蛮大的,如果对表单样式没有特殊的需求,Bootstrap中的表单样式可以满足需求,可以通过

Flask-Bootstrap

提供的辅助函数快速的渲染表单,只需要如下两步:

{% import "bootstrap/wtf.html" as wtf %}{{ wtf.quick_form(form) }}

例如登录的H5模板就是这样做的。

form.hidden_tag()

模板参数将被替换为一个隐藏字段,用来实现在配置中激活的 CSRF 保护。如果你已经激活了CSRF,这个字段需要出现在你所有的表单中。

在2.2中,如果点击表单提交按钮,所有的表单都能成功通过校验,则

form.validate_on_submit()

的值为

True

,否则校验失败,网页会出现对应提示。如果有两个提交按钮,那么在校验成功后,还需要判断点击的是哪个按钮,否则所有的按钮都执行了同一个操作。例如我们的文章发布和保存按钮,当表单类中的按钮字段的

data

属性为

True

则代表该按钮被点击,例如:

if form.publish.data: # 发布elif form.save.data: # 保存草稿

3.4、jQuery

有些页面需要在相关操作后修改控件的CSS样式,例如文章详情的喜欢和取消喜欢按钮,最简单的方式是操作成功后直接刷新整个页面,但这样体验并不好,更好的方式是局部刷新。这里直接使用jQuery(Bootstrap也提供了类似的操作,同时包含了jQuery,不需要单独导入jQuery)来实现。使用

jQuery

强大的选择器功能可以方便的得到要操作的

DOM节点

,按钮的点击也是发起一个请求,

jQuery

也集成了

ajax

,可以方便的处理请求,在请求完成后根据响应结果来更改

DOM节点

的样式。看下按钮的点击事件:

favourite = function (id) { if ($('.blog-favourite-btn').length > 0) {//取消喜欢$.get('/manage/blog/cancel_favourite', { id: id }).done(function (data) { $('.blog-favourite-btn span').removeClass('glyphicon-heart').addClass('glyphicon-heart-empty'); $('.blog-favourite-btn').removeClass('blog-favourite-btn').addClass('blog-unfavourite-btn'); }) } else if ($('.blog-unfavourite-btn').length > 0) {//喜欢 $.get('/manage/blog/favourite', { id: id }).done(function (data) { if ('200' === data) { $('.blog-unfavourite-btn span').removeClass('glyphicon-heart-empty').addClass('glyphicon-heart'); $('.blog-unfavourite-btn').removeClass('blog-unfavourite-btn').addClass('blog-favourite-btn'); } if ('403' === data) { alert('没有操作权限'); } }) } }

4、Markdown

书中使用的是

Flask-PageDown

Markdown

两个库来实现对Markdown功能的支持,但是不够理想,有些Markdown语法并不能很好的支持,例如

Flask-PageDown

实时预览时并不支持代码块和表格等。最后使用了marked这个库,它是一个全功能的Markdown解析器和编译器,用JavaScript编写,构建速度快,其实就是实时将用Markdown语法编辑的内容转换成对应的HTML预览,但是没有CSS样式的HTML还是有点丑,github-markdown-css是一个不错的选择,可以帮助我们实现github风格的Markdwon预览。既然是要编辑文章那么直接使用HTML里的

肯定难以实现理想的效果,这里使用了ace,它是一个用JavaScript编写的独立代码编辑器,下载

...

Python-Flask系列(第七篇:Flask完整的开始) 流量视频课程

img

小牛

关注

前面几篇,我们了解了一些基础的请求响应以及相关的一些知识,基本已经走完了一个最简单的hello world结构。

那么,今天我们就从整体出发,在浅谈几点补充知识。

1.Flask 上下文

2.Flask 请求钩子

3.Flask 状态码响应

4.Flask 扩展

Flask从客户端接收请求时候,要让视图函数访问一些对象获取一定的参数,这样才能处理请求。"请求对象"就是一个很实际的例子,它封装了客户端发送的HTTP请求的内容。

如果,请求对象是一次请求的单一变量,那么这样就要在每个视图函数的参数项中添加一个参数,繁杂不说,而且难以维护。

为了应对这种情况,Flask提供了"上下文"机制,将一些变量设置为全局变量,一次来解决这类需求。

但是,"请求对象"request必然不能多用户通用,只能一次请求中所有的操作可以通用全局访问,这说明,全局变量有线程内和跨线程的。下面是具体分类和功能:

变量名称

上下文

作用说明

current_app

程序上下文

当前已激活程序的实例属性名称

g

处理请求时,用作临时存储的对象。每次请求都会重设这个变量。

request

请求上下文

请求对象,封装了客户端HTTP请求的所有内容。

session

用户会话,用于存储请求之间需要记住的值的字典。

注:在使用current_app之前,需要激活上下文。通过app.app_context()来获得一个程序上的上下文。

具体命令:

app_ctx = app.app_context()

app_ctx.push()

我们都知道,在一般程序的启动开始,必然有针对程序运行环境的配置检查等一系列只在开始进行却不会重复或者需要在每次关闭程序时候执行的环境清理的一些内部操作。

那么Flask是怎么实现此类功能的呢?这里就需要我们引入Flask钩子的概念。以此来注册通用函数,被注册的函数可以在被分发到视图函数之前或者之后执行。

请求钩子通过修饰器来实现。Flask主要支持以下四种钩子:

钩子

作用

before_first_request

注册一个函数,在处理第一个请求之前运行。

before_request

注册一个函数,在每次执行请求之前运行。

after_request

注册一个函数,如果没有未处理的异常抛出,在每次请求执行后运行。

teardown_request

注册一个函数,即使有异常抛出,也在每次请求执行后运行。

注:在请求钩子注册的函数和视图函数之间,共享的数据一般保存在上文提到的程序上下文变量g中。

我们都知道,在请求响应中,如果响应码为200就是成功响应,404就是找不到页面,以及其他的一些代码都有对应的含义。

那么我们在后台处理完请求之后,怎么讲制定的状态码返回呢?之前的示例中为什么没有见到有返回状态码的例子呢?

那么我们现在就来讲解,如果想要在处理的请求响应中返回指定的状态码,可以通过以下几种方式:

第一种:元组值响应

@app.route('/user/',methods=["GET","POST"])def users():return "

hello , user .

",200

这一种最直接,在返回值元组后面加上状态码,以逗号分隔就好。

第二种:response响应

@app.route('/user/',methods=["GET","POST"])def users():response = make_response("

hello , user .

")response.set_cookie("answer","200")return response

通过make_response()函数来构建响应,在cookie中添加字典值。

系列伊始,我们就介绍了,Flask是一个微框架,只保留了最核心的功能,其他的功能需要根据实际需求和喜好,去安装对应的扩展插件。

此处以flask-script为例:

首先使用pip安装:

pip install flask-script

其次在程序开始导入flask-script中的Manager模块:

from flask_script import Manager

生成Manager的app处理实例:

manager = Manager(app)

最终,在末尾的程序运行处,以实例manager进行运行程序:

if __name__ == '__main__':manager.run()

此时代码完成后,已经不能再IDE中通过运行键来运行项目,需要在cmd中切换到项目目录,运行如下命令:

python project.py runserver --host 0.0.0.0

最终,你会看到程序运行的提示反馈。此时的project可以通过其他机器访问本机ip来进行访问项目。

牛牛牛

学习python flask之九:如何debug以及解决之前代码中的bug 公司视频课程

img

Zarate

关注

处理bug的最好方式是亲自经历一次。在之前完成的应用中有一个bug。怎么触发这个bug呢?首先确保你的应用中注册了至少两个用户,登录其中一个用户,打开profile页并点击编辑链接。在编辑profile页面中,username改为另一个已经注册的用户,然后bug出现了。

此时建议打开debug功能, export FLASK_DEBUG=1,再触发一次该bug,就能看到如下的debug信息。

出现这个bug的原因是在把username写入数据库时,写入了一个已经存在的用户名,而用户名定义成唯一,因此出现错误。

回想一下,RegistrationForm已经验证了username,但是编辑表单的需求有点不同。注册中,需要确保用户输入的用户名在数据库中不存在。编辑profile时也需要做相应的检查。

解决这个问题的方法是添加对username的检查。

由于EditProfileForm的构造函数增加了参数,因此创建它的对象时需要添加参数。

form = EditProfileForm(current_user.username)

然后在验证参数时显式的调用form.validate_username函数。

img

在线咨询

建站在线咨询

img

微信咨询

扫一扫添加
动力姐姐微信

img
img

TOP