Python Flask微框架安装与基础说明


Flask是一个用python写成的微框架,能用简单代码实现最基本的web服务器端。一般在服务器上使用python都会先建立一个python的虚拟环境。

1.  python 虚拟环境创建

  1. mkdir myenv
  2. python3 -m venv myenv  # 创建虚拟环境,需要先建立文件夹。

注:建立虚拟环境可以保证安装模块不受系统权限影响,且不影响系统的python环境。

  1. source  myvenv/bin/activate  # 进入虚拟环境。
  2. ./myvenv/bin/python xxxx.py #直接调用虚拟环境的python

:也可以使用绝对路径的python 指令来调用虚拟环境的python,常用在脚本启动中。

  1. deactivate  # 退出虚拟环境(在虚拟环境下输入)

2. python包管理工具pip和Flask安装。

  1. sudo apt-get install python-pip # 安装pip 包管理工具
  2. pip install Flask # 安装flask框架

3. 若需要批量安装输入 pip install -r common.txt

common.txt 写明需要安装的包和版本,如下:

  1. Flask==0.10.1
  2. Flask-Bootstrap==3.0.3.1
  3. Flask-Migrate==1.1.0
  4. Flask-SQLAlchemy==1.0
  5. Flask-Script==0.6.6
  6. Flask-WTF==0.9.4
  7. Jinja2==2.7.1
  8. Werkzeug==0.9.4

注:实际使用过程中,按照需求,去寻找对应的modules,按照pip install的方式安装到你的虚拟环境中,就可以开始你的flask之旅了。

flask web 编程学习笔记5:E-Mail


Flask 可快速简单的实现E-Mail的功能,可以用于用户注册,找回密码等功能,且邮件内容灵活。
复制下述代码的内容,修改成自己的邮箱和一些配置文件就可以实现简单的邮件发送功能。

  1. ''' 
  2.     Note5. E-Mail And Example 
  3. '''  
  4. #  
  5. #########################################################################  
  6. #  
  7. #     E-Mail 由flask-mail提供支持,若不验证,Flask-Mail 会连接localhost   
  8. # 上的端口25,无需验证即可发送电子邮件。  
  9. #     安装方法:pip install flask-mail  
  10. #  
  11. #########################################################################  
  12. #  
  13. import os  
  14. from flask import Flask  
  15. #  
  16. from flask.ext.mail import Mail, Message  
  17. #  
  18. from threading import Thread  
  19. #  
  20. app = Flask(__name__)  
  21. mail = Mail(app)  
  22. #  
  23. # 若配置外部邮箱使用如下方式:  
  24. #  
  25. app.config['MAIL_SERVER'] = 'xxx.mxhichina.com'  
  26. app.config['MAIL_PORT'] = 587  
  27. app.config['MAIL_USE_TLS'] = True  
  28. #  
  29. # windows使用如下方式设置环境变量即可:  
  30. # (venv) $ set MAIL_USERNAME=  
  31. # (venv) $ set MAIL_PASSWORD=  
  32. #  
  33. app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')  
  34. #  
  35. # Linux使用如下方式设置环境变量即可:  
  36. # (venv) $ export MAIL_USERNAME=  
  37. # (venv) $ export MAIL_PASSWORD=  
  38. #  
  39. app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')  
  40. #  
  41. # Flask-Mail SMTP服务器的配置:  
  42. # |--------------------------------------------------------------------------------  
  43. # | 配  置         默认值         说  明  
  44. # |--------------------------------------------------------------------------------  
  45. # | MAIL_SERVER     localhost   电子邮件服务器的主机名或IP 地址  
  46. # | MAIL_PORT       25          电子邮件服务器的端口  
  47. # | MAIL_USE_TLS    False       启用传输层安全(Transport Layer Security,TLS)协议  
  48. # | MAIL_USE_SSL    False       启用安全套接层(Secure Sockets Layer,SSL)协议  
  49. # | MAIL_USERNAME   None        邮件账户的用户名  
  50. # | MAIL_PASSWORD   None        邮件账户的密码  
  51. # | --------------------------------------------------------------------------------  
  52. #  
  53.   
  54. app.config['FLASKY_MAIL_SUBJECT_PREFIX'] = '[Flasky]'  
  55. #  
  56. app.config['FLASKY_MAIL_SENDER'] = 'Flasky Admin <flasky@example.com>'  
  57. # ...  
  58. app.config['FLASKY_ADMIN'] = os.environ.get('FLASKY_ADMIN')  
  59. # ...  
  60.   
  61. def send_email(to, subject, template, **kwargs):  
  62.     msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,  
  63.     sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])  
  64.     msg.body = render_template(template + '.txt', **kwargs)  
  65.     msg.html = render_template(template + '.html', **kwargs)  
  66.     mail.send(msg)  
  67.   
  68. def send_async_email(app, msg):  
  69.     with app.app_context():  
  70.         mail.send(msg)  
  71.           
  72. def thr_send_email(to, subject, template, **kwargs):  
  73.     msg = Message(app.config['FLASKY_MAIL_SUBJECT_PREFIX'] + subject,\  
  74.                   sender=app.config['FLASKY_MAIL_SENDER'], recipients=[to])  
  75.     msg.body = render_template(template + '.txt', **kwargs)   
  76.     msg.html = render_template(template + '.html', **kwargs)  
  77.     thr = Thread(target=send_async_email, args=[app, msg])  
  78.     thr.start()  
  79.     return thr  
  80.       
  81.       
  82. @app.route('/', methods=['GET', 'POST'])  
  83. def index():  
  84.     form = NameForm()  
  85.     if form.validate_on_submit():  
  86.         user = User.query.filter_by(username=form.name.data).first()  
  87.         if user is None:  
  88.             user = User(username=form.name.data)  
  89.             db.session.add(user)  
  90.             session['known'] = False  
  91.             if app.config['FLASKY_ADMIN']:  
  92.                 send_email(app.config['FLASKY_ADMIN'], 'New User',\  
  93.                            'mail/new_user', user=user)  
  94.         else:  
  95.             session['known'] = True  
  96.         session['name'] = form.name.data  
  97.         form.name.data = ''  
  98.         return redirect(url_for('index'))  
  99.     return render_template('index.html',\   
  100.                            form=form,\   
  101.                            name=session.get('name'),\  
  102.                            known=session.get('known', False))          
  103.   
  104. if __name__ == '__main__':  
  105.     app.run(debug=True)  

flask web 编程学习笔记4:SQL


Flask 支持多种数据库,并采用sqlalchemy 作为常用ORM,链接数据库也比较方便。
1. 复制执行下述代码,即可实现数据库的链接。
2. 用编辑器打开数据库文件,可以看到自己添加的数据内容。

  1. ''' 
  2.     Note4. SQL Database And Example 
  3. '''  
  4. #  
  5. #########################################################################  
  6. #  
  7. #     数据库按照一定规则保存程序数据,程序再发起查询取回所需  
  8. # 的数据。Web 程序最常用基于关系模型的数据库,这种数据库也称  
  9. # 为SQL 数据库,因为它们使用结构化查询语言。不过最近几年文档  
  10. # 数据库和键值对数据库成了流行的替代选择,这两种数据库合称  
  11. # NoSQL数据库。  
  12.   
  13. #########################################################################  
  14. #  
  15. # 1) Flask 可用MySQL、Postgres、SQLite、Redis、MongoDB或者CouchDB。  
  16. #    SQLAlchemy ORM 作为一个数据库工具,常被用于项目。  
  17. #  
  18. # 2) SQLAlchemy安装: pip install flask-sqlalchemy.  
  19. #  
  20. # 3) SQLAlchemy支持以下数据库,方法如下:  
  21. # |----------------------------------------------------------------------  
  22. # | 数据库            | 引擎URL  
  23. # |----------------------------------------------------------------------  
  24. # | MySQL             | mysql://username:password@hostname/database  
  25. # | Postgres          | postgresql://username:password@hostname/database  
  26. # | SQLite(Unix)    | sqlite:////absolute/path/to/database  
  27. # | SQLite(Windows) | sqlite:///c:/absolute/path/to/database  
  28. # |----------------------------------------------------------------------  
  29.   
  30. # 以下按照sqlite3 进行说明。  
  31. #  
  32. from flask import Flask,render_template, session, redirect, url_for  
  33. from flask.ext.sqlalchemy import SQLAlchemy  
  34. from flask.ext.bootstrap import Bootstrap  
  35. from flask.ext.wtf import Form  
  36. from wtforms import StringField, SubmitField  
  37. from wtforms.validators import Required  
  38. import os  
  39.   
  40. # 得到项目路径的常用方法。  
  41. basedir = os.path.abspath(os.path.dirname(__file__))  
  42.   
  43. # Flask 实例化  
  44. app = Flask(__name__)  
  45. # 定义app数据库文件及路径。  
  46. app.config['SQLALCHEMY_DATABASE_URI'] =\  
  47. 'sqlite:///' + os.path.join(basedir, 'data.sqlite')  
  48. # SQLALCHEMY_COMMIT_ON_TEARDOWN配置。  
  49. app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True  
  50. #  
  51. app.config['SECRET_KEY'] = 'hard to guess string'  
  52. # db 对象是SQLAlchemy 类的实例,表示程序使用的数据库,同时还获得了  
  53. # Flask-SQLAlchemy提供的所有功能。  
  54. db = SQLAlchemy(app)  
  55. #  
  56. bootstrap = Bootstrap(app)  
  57. #  
  58. #     采用类继承的方式定义新的数据库表格,类变量__tablename__ 定义在  
  59. # 数据库中使用的表名。Column函数定义表中元素,其参数特点如下:  
  60. #     db.Column(类型,其他参数,....)  
  61. #  
  62. # 1) 类型表.  
  63. # |-------------------------------------------------------------------------  
  64. # | 类型名       | Python类型          | 说  明  
  65. # |-------------------------------------------------------------------------  
  66. # | Integer      | int                 | 普通整数,一般是32 位  
  67. # | SmallInteger | int                 | 取值范围小的整数,一般是16 位  
  68. # | BigInteger   | int 或long          | 不限制精度的整数  
  69. # | Float        | float               | 浮点数  
  70. # | Numeric      | decimal.Decimal     | 定点数  
  71. # | String       | str                 | 变长字符串  
  72. # | Text         | str                 | 变长字符串,对较长或不限长度的字符串  
  73. # |------------------------------------| 做了优化  
  74. # | Unicode      | unicode             | 变长Unicode 字符串  
  75. # | UnicodeText  | unicode             | 变长Unicode 字符串,对较长或不限长度  
  76. # |------------------------------------| 的字符串做了优化  
  77. # | Boolean      | bool                | 布尔值  
  78. # | Date         | datetime.date       | 日期  
  79. # | Time         | datetime.time       | 时间  
  80. # | DateTime     | datetime.datetime   | 日期和时间  
  81. # | Interval     | datetime.timedelta  | 时间间隔  
  82. # | Enum         | str                 | 一组字符串  
  83. # | PickleType   | 任何Python          | 对象自动使用Pickle 序列化  
  84. # | LargeBinary  | str                 | 二进制文件  
  85. # |---------------------------------------------------------------------------  
  86. #  
  87. # 2) 其他属性表  
  88. # |---------------------------------------------------------------------------  
  89. # | 选项名      | 说  明  
  90. # |---------------------------------------------------------------------------  
  91. # | primary_key | 如果设为True,这列就是表的主键  
  92. # | unique      | 如果设为True,这列不允许出现重复的值  
  93. # | index       | 如果设为True,为这列创建索引,提升查询效率  
  94. # | nullable    | 如果设为True,这列允许使用空值;如果设为False,这列不允许使用  
  95. # |-------------| 空值  
  96. # | default     | 为这列定义默认值  
  97. # |---------------------------------------------------------------------------  
  98. #  
  99. class Role(db.Model):  
  100.     __tablename__ = 'roles'  
  101.     id = db.Column(db.Integer, primary_key=True)  
  102.     name = db.Column(db.String(64), unique=True)  
  103.     #     db.relationship() 中的backref 参数向User 模型中添加一个role 属性,  
  104.     # 从而定义反向关系。这一属性可替代role_id 访问Role 模型,此时获取的是模  
  105.     # 型对象,而不是外键的值。  
  106.     users = db.relationship('User', backref='role')  
  107.     def __repr__(self):  
  108.         return '' % self.name  
  109.           
  110. class User(db.Model):  
  111.     __tablename__ = 'users'  
  112.     id = db.Column(db.Integer, primary_key=True)  
  113.     username = db.Column(db.String(64), unique=Trueindex=True)  
  114.     #     关系使用users 表中的外键连接了两行。添加到User 模型中的role_id 列  
  115.     # 被定义为外键,就是这个外键建立起了关系。传给db.ForeignKey() 的参数  
  116.     # 'roles.id' 表明,这列的值是roles 表中行的id 值。  
  117.     role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))  
  118.     def __repr__(self):  
  119.         return '' % self.username  
  120.   
  121. class NameForm(Form):  
  122.     name = StringField('What is your name?', validators=[Required()])  
  123.     submit = SubmitField('Submit')  
  124.       
  125. @app.route('/', methods=['GET', 'POST'])  
  126. def index():  
  127.     form = NameForm()  
  128.     if form.validate_on_submit():  
  129.         user = User.query.filter_by(username=form.name.data).first()  
  130.         if user is None:  
  131.             user = User(username = form.name.data)  
  132.             db.session.add(user)  
  133.             session['known'] = False  
  134.         else:  
  135.             session['known'] = True  
  136.         session['name'] = form.name.data  
  137.         form.name.data = ''  
  138.         return redirect(url_for('index'))  
  139.     return render_template('sql.html',\  
  140.                            form = form, name = session.get('name'),\  
  141.                            known = session.get('known', False))  
  142. if __name__ == '__main__':  
  143.     db.create_all()  
  144.     app.run(debug=True)  

flask web 编程学习笔记3:表单


表单作为一个常用的html选项,flask使用flask-WTF实现了常用的表单功能,实现简单方便。

复制代码,并执行,可以在浏览器中看到输入框:

  1. ''' 
  2.     Note3. WTF And Example 
  3. '''  
  4. #  
  5. #########################################################################  
  6. #  
  7. #     使用Flask-WTF可以处理表单,按照如下方式进行安装:  
  8. # pip install flask-wtf  
  9. #  
  10. #########################################################################  
  11. #  
  12. from flask import Flask, render_template, session, redirect, url_for, flash  
  13. # wtf about import file  
  14. from flask.ext.wtf import Form  
  15. from wtforms import StringField, SubmitField  
  16. from wtforms.validators import Required  
  17. from flask.ext.bootstrap import Bootstrap  
  18. #  
  19. app = Flask(__name__)  
  20. #  
  21. # 1) Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request   
  22. # Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时  
  23. # 就会引发CSRF 攻击。  
  24. # 2) 为了实现CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF使用  
  25. # 这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。  
  26. #  
  27. app.config['SECRET_KEY'] = 'hard to guess string'  
  28. #  
  29. bootstrap = Bootstrap(app)  
  30. #  
  31. class NameForm(Form):  
  32.     #  
  33.     # 使用Flask-WTF 时,每个Web 表单都由一个继承自Form 的类表示。  
  34.     # NameForm 表单中有一个名为name的文本字段和一个名为submit的提交按钮。  
  35.     # Form 基类由Flask-WTF扩展定义,所以从flask.ext.wtf中导入。字段和验  
  36.     # 证函数却可以直接从WTForms 包中导入。  
  37.     #  
  38.     name = StringField('What is your name?', validators=[Required()])  
  39.     submit = SubmitField('Submit')  
  40.   
  41. # Form支持的字段:  
  42. # |----------------------------------------------------------------------  
  43. # | 字段类型            | 说  明  
  44. # |----------------------------------------------------------------------  
  45. # | StringField         | 文本字段  
  46. # | TextAreaField       | 多行文本字段  
  47. # | PasswordField       | 密码文本字段  
  48. # | HiddenField         | 隐藏文本字段  
  49. # | DateField           | 文本字段,值为datetime.date 格式  
  50. # | DateTimeField       | 文本字段,值为datetime.datetime 格式  
  51. # | IntegerField        | 文本字段,值为整数  
  52. # | DecimalField        | 文本字段,值为decimal.Decimal  
  53. # | FloatField          | 文本字段,值为浮点数  
  54. # | BooleanField        | 复选框,值为True 和False  
  55. # | RadioField          | 一组单选框  
  56. # | SelectField         | 下拉列表  
  57. # | SelectMultipleField | 下拉列表,可选择多个值  
  58. # | FileField           | 文件上传字段  
  59. # | SubmitField         | 表单提交按钮  
  60. # | FormField           | 把表单作为字段嵌入另一个表单  
  61. # | FieldList           | 一组指定类型的字段  
  62. # |------------------------------------------------------------------------  
  63. # WTForms 内建的验证函数:  
  64. # |------------------------------------------------------------------------  
  65. # | 验证函数        | 说  明  
  66. # |------------------------------------------------------------------------  
  67. # | Email           | 验证电子邮件地址  
  68. # | EqualTo         | 比较两个字段的值;常用于要求输入两次密码进行确认的情况  
  69. # | IPAddress       | 验证IPv4 网络地址  
  70. # | Length          | 验证输入字符串的长度  
  71. # | NumberRange     | 验证输入的值在数字范围内  
  72. # | Optional        | 无输入值时跳过其他验证函数  
  73. # | Required        | 确保字段中有数据  
  74. # | Regexp          | 使用正则表达式验证输入值  
  75. # | URL             | 验证URL  
  76. # | AnyOf           | 确保输入值在可选值列表中  
  77. # | NoneOf          | 确保输入值不在可选值列表中  
  78. # |------------------------------------------------------------------------  
  79. #  
  80.   
  81.   
  82. @app.route('/', methods=['GET', 'POST'])  
  83. def index():  
  84.     # 用户第一次访问程序时,服务器会收到一个没有表单数据的GET 请求,  
  85.     # 所以validate_on_submit() 将返回False。if 语句的内容将被跳过,  
  86.     # 通过渲染模板处理请求,并传入表单对象和值为None 的name 变量作  
  87.     # 为参数。用户会看到浏览器中显示了一个表单。  
  88.     name = None  
  89.     form = NameForm()  
  90.     # 提交表单后,如果数据能被所有验证函数接受,那么validate_on_submit()   
  91.     # 方法的返回值为True,否则返回False。  
  92.     if form.validate_on_submit():  
  93.         name = form.name.data          
  94.         form.name.data = ''          
  95.     return render_template('wtf.html', form=form, name=name)  
  96.       
  97.     ''' 
  98.     or : 重定向的方式,采用session记录上下文。 
  99.         session['name'] = form.name.data 
  100.         return redirect(url_for('index')) 
  101.     return render_template('wtf.html', form=form, name=session.get('name')) 
  102.      
  103.     or : flash 消息用来提示客户状态值。 
  104.         if old_name is not None and old_name != form.name.data: 
  105.             flash('Looks like you have changed your name!') 
  106.             session['name'] = form.name.data 
  107.             return redirect(url_for('index')) 
  108.     return render_template('index.html',\ 
  109.                            form = form,\ 
  110.                            name = session.get('name')) 
  111.     '''  
  112. # 注,传递flash消息时,需要修改html,增加:{% for message in get_flashed_messages() %}      
  113.       
  114. if __name__ == '__main__':  
  115.     app.run(debug=True)