python flask框架 统计_Python-Flask框架

(本文后期会重新整理,敬请期待)

URL和视图

安装Homebrew

在终端输入以下代码,安装Homebrew:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Python安装

mac环境下默认安装了python 2.7,安装3.6需要用以下代码:

brew install python3

Python虚拟环境安装

因为python的框架版本更新迭代速度太快,有时需要在一台电脑上存在一个框架的多个版本,这时就需要虚拟环境。通过以下代码安装:

pip3 install virtualenv

虚拟环境管理工具virtualenvwrapper可以很便捷的新建、删除、切换虚拟环境。virturalenvwrapper可以通过一下代码安装:

pip3 install virtualenvwrapper

在使用virturalenvwrapper之前,需要对 virtualenvwrapper 进行配置。它需要指定一个环境变量,叫做 WORKON_HOME,并且需要运行一下它的初始化工具 virtualenvwrapper.sh,这个脚本默认安装在 /usr/local/bin/ 目录下。WORKON_HOME 就是它将要用来存放各种虚拟环境目录的目录,这里我们可以设置为 ~/.Python/Envs。通过以下方式将配置代码加入.bash_profile中

修改方式

vim .bash_profile

open -e .bash_profile

配置代码

export WORKON_HOME=$HOME/.Python/Envs

export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3

source /usr/local/bin/virtualenvwrapper.sh

virtualenvwrapper常用指令:

mkvirtualenv env1 //创建虚拟环境

workon //列出虚拟环境

workon Flask_env //使用虚拟环境env1

deactivate //退出虚拟环境

rmvirtualenv env1 //删除虚拟环境env1

flask 安装

进入创建的虚拟环境,在虚拟环境下安装flask,安装指令如下:

pip3 install flask

第一个flask程序

from flask import Flask

app = Flask(__name__)

@app.route('/')

def hello_world():

return 'Hello world!'

if __name__ == '__main__'

app.run()

debug 模式

在app.run()中传入一个关键字参数debug,app.run(debug=Ture),就设置当前项目为debug模式。

debug模式的两大功能:

当程序出现问题时,可以在页面中看到错误信息和出错的位置。

只要修改了项目中的Python文件,程序会自动加载,不需要手动重启服务器。

使用配置文件

新建一个'config.py'文件

在主app文件中导入这个文件,并且配置到app中,示例代码如下

import config

app.config.from_object(config)

还有许多的其他参数,都是放在这个配置文件中,比如‘SECRET_KEY‘和’SQLALCHEMY‘。

URL 传参

参数的作用:可以在相同的URL中指定不同的参数,来加载不同的数据。

在flask中使用参数:

@app.route('/article/')

def article(id):

return u'你请求的参数是:%s' % id

* 参数需要放在两个尖括号中

* 视图函数中需要放和url中的参数同名的参数

URL 反转

什么叫反转URL:从视图函数到URL的转换叫做反转URL

href="{{ url_for('index') }}"

反转URL的用处

在页面重定向的时候,会使用URL反转

在模版中,也会使用URL反转

页面跳转和重定向

用处:在用户访问一些需要登录的界面时,如果用户没有登录,那么可以让它重定向到登录页面

代码实现:

from flask import Flask,redirect,url_for

redirect(url_for('login'))

Jinjia2模版

Flask渲染Jinjia2模版和传参

如何渲染模版

模版放在‘templates’文件夹下

从‘flask’中导入‘render_template’函数

从视图函数中,使用‘render_template’函数,渲染模版。注意,只需要填写模版的名字,不需要填写‘templates’这个文件路径

模版传参:

如果只有一个或少量参数,直接在‘render_template’函数中添加关键字参数就可以了。

如果有多个参数,那么可以先把所有的参数放到字典中,然后在‘render_template’中,使用**将字典转换成关键参数传递进去,这样的代码更方便管理和使用。

在模版中,使用一个变量的语法是{{ params }}

访问模版中的属性或是字典,可以通过{{ params.property }}的形式,或者使用{{ params['property'] }}。

if判断语句

语法

{% if xxx %}

{% eles %}

{% endif %}

if的使用和python相差无几

for循环遍历

字典的遍历语法和python一样,可以使用‘items()’、‘keys()’、‘values()’、‘iteritems()’、‘iterkeys()’、‘itervalues()’

{% for k,v in user.items() %}

{{ k }}:{{ v }}

{% endfor %}

列表的遍历与python一样

{% for website in websites %}

{{ website }}

{% endfor %}

过滤器

介绍和语法

介绍:过滤器可以处理变量,把原始的变量经过处理后再展示出来,作用的对象是变量

语法:

{{ params|default('xxx') }}

default过滤器:如果当前变量不存在,这时候可以指定默认值

length过滤器:求列表、字符串、字典和元祖的长度

{{ params|length }}

继承和block

继承的作用和语法

作用:可以把公共的代码放在父模版中,避免每一个模版写同样的代码

语法:

{% extends 'base.html' %}

block实现:

作用:可以让子模版实现自己的需求,父模版需要提前定义

{% block main %}{% endblock%}

注意点:子模版中的代码必须放在block块中

{% block main %}

这是登录页面

{% endblock %}

URL链接和加载静态文件

使用‘url_for(视图函数名称)’可以反转成url

加载静态文件:

语法:‘url_for('static',filename='路径')’

flask会从‘static’文件夹中开始寻找,不需要写‘static’这个路径

可以加载css、js、image文件

SQLAlchemy数据库

Mac下数据库的安装

MySql下载链接

Mac上安装Mysql后,在系统偏好设置里启动MySql服务

配置环境变量:

进入/usr/local/mysql/bin,查看此目录下是否有mysql

执行以下指令:

进入vim

vim ~/.bash_profile

添加mysql路径

PATH=$PATH:/usr/local/mysql/bin

按esc,输入‘:wq’保存退出

激活配置文件

source ~/.bash_profile

数据库相关指令:

mysql -u username -p

show databases

mysqlclient安装

进入虚拟环境,安装mysql-connector-c

brew install mysql-connector-c

修改mysql_config文件的配置,位于/usr/local/bin/mysql_config

原代码:

libs="-L$pkglibdir"

libs="$libs -l "

更改后代码:

libs="-L$pkglibdir"

libs="$libs -lmysqlclient -lssl -lcrypto"

安装mysqlclient:

pip3 install mysqlclient

Flask-SQLAlchemy的介绍与安装

ORM:Object Relationship Mapping(模型关系映射)

flask-sqlalchemy是一套ORM框架

ORM的好处:可以让我们操作数据库和操作对象一样,非常方便。因为一个表就抽象成一个类,一条数据就抽象成该类的一个对象。

安装‘Flask-sqlalchemy’:

pip install flask-sqlalchemy

Flask-SQLAlchemy的使用

初始化和设置数据库配置信息:

使用flask_sqlalchemy中的SQLAlchemy进行初始化:

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

db = SQLAlchemy(app)

设置配置信息,在config.py文件中添加以下配置信息:

* dialect+driver://username:password@host:port/database *

DIALECT = 'mysql'

DRIVER = 'mysqldb'

USERNAME = 'root'

PASSWORD = 'Gao123456'

HOST = 'localhost'

PORT = '3306'

DATABASE = 'db_demo1'

SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)

SQLALCHEMY_TRACK_MODIFICATIONS = False

在主app文件中添加配置文件(config.py)

配置文件和主app文件在同一目录下:

import config

app.config.from_object(config)

配置文件来自于其他目录(./config/config.py)

目录需要包含一个叫做 __init__.py 的文件

from config.config

app.config.from_object(config.config_demo1)

测试

db.creat_all()

如果没有报错,说明配置没有问题,如果有错误,可以根据错误进行修改

SQLAlchemy模型与表映射

模型需要继承自‘db.Model’,然后需要映射到表中的属性,必须写成‘db.Column’的数据类型。

数据类型:

db.Integer:int

db.String:varchar()

db.Text:text

其他参数:

Primary_key:代表将这个字段设置为主键

autoincrement:代表这个主键为自增长

nullable:代表这个字段是否为空,默认为空。可以将这个值设置为‘False’,那么在数据库中,这个值就不能为空了。

最后需要调用‘db.create_all()’来讲模型真正的创建到数据库中。

class Article(db.Model):

__tablename__ = 'article'#指定表名

id = db.Column(db.Integer,primary_key=True,autoincrement=True)

title = db.Column(db.String(100),nullable=False)

content = db.Column(db.Text,nullable=False)

SQLAlchemy数据增删改查

增加

# 增加

article1 = Article(title='aaa',content='bbb')

db.session.add(article1)

# 事务

db.session.commit()

查找

# 查询

article1 = Article.query.filter(Article.title == 'aaa').first()

print('title:%s' % article1.title)

print('comment:%s' % article1.content)

修改

# 修改

# 1.先把需要修改的数据查找出来

article1 = Article.query.filter(Article.title == 'aaa').first()

# 2.将查找到的数据所要修改的地方进行修改

article1.title = 'new title'

# 3.做事务提交

db.session.commit()

删除

# 删除

# 1.把需要删除的数据查找出来

article1 = Article.query.filter(Article.title == 'aaa').first()

# 2.删除数据

db.session.delete(article1)

# 3.做事务提交

db.session.commit()

Flask_SQLAlchemy外键及其关系

外键:

class User(db.Model):

__tablename__ = 'user'

id = db.Column(db.Integer,primary_key=True,autoincrement=True)

username = db.Column(db.String(100),nullable=False)

class Article(db.Model):

__tablename__ = 'article'

id = db.Column(db.Integer,primary_key=True,autoincrement=True)

title = db.Column(db.String(100),nullable=False)

content = db.Column(db.Text,nullable=False)

author_id = db.Column(db.Integer,db.ForeignKey('user.id'))

author = db.relationship('User',backref=db.backref('articles'))

author = db.relationship('User',backref=db.backref('articles'))解释:

给‘Article’这个模型添加一个‘author’属性,可以访问这篇文章的作者的数据,就像访问普通模型一样

‘backref’是定义反向引用,可以通过‘User.articles’访问这个模型所写的所有文章

多对多关系

多对多的关系,要通过一个中间表进行关联

中间表,不能通过‘class’的方式创建,只能通过‘db.Table’的方式创建

class Article(db.Model):

__tablename__ = 'article'

id = db.Column(db.Integer,primary_key=True,autoincrement=True)

title = db.Column(db.String(100),nullable=False)

tags = db.relationship('Tag',secondary='article_tag',backref=db.backref('articles'))

class Tag(db.Model):

__tablename__ = 'tag'

id = db.Column(db.Integer,primary_key=True,autoincrement=True)

name = db.Column(db.String(100),nullable=False)

article_tag = db.Table('article_tag',

db.Column('article_id',db.Integer,db.ForeignKey('article.id'),primary_key=True),

db.Column('tag_id',db.Integer,db.ForeignKey('tag.id'),primary_key=True)

)

设置关联:

tags = db.relationship('Tag',secondary='article_tag',backref=db.backref('articles'))

访问和添加数据可以通过一下方式操作:

添加数据

article1 = Article(title='iPhone')

article2 = Article(title='iPad')

tag1 = Tag(name='Easy')

tag2 = Tag(name='Good')

article1.tags.append(tag1)

article1.tags.append(tag2)

article2.tags.append(tag1)

article2.tags.append(tag2)

db.session.add(article1)

db.session.add(article2)

db.session.add(tag1)

db.session.add(tag2)

db.session.commit()

访问数据

article1 = Article.query.filter(Article.title =='iPhone').first()

tags = article1.tags

for tag in tags:

print (tag.name)

Flask_script的介绍与安装

Flask-script:其作用是可以通过命令行的形式来操作FLask。例如通过命令跑一个开发版本的服务器,设置数据库,定时任务等。

安装:进入到虚拟环境中,使用一下命令安装:

pip install flask-script

如何直接在主‘manager.py’中写命令,那么在终端只需要python manager.py command_name就可以了。

如果把一些命令集中在一个文件中,那么在终端就需要输入一个父命令,比如python manager.py db init

例子:

from flask_script import Manager

from flask_script_demo import app

from db_script import DBmanager

manager = Manager(app)

@manager.command

def runserver():

print('The server is running!')

manager.add_command('db',DBmanager)

if __name__ == '__main__':

manager.run()

有子命令的例子:

from flask_script import Manager

DBmanager = Manager()

@DBmanager.command

def init():

print('数据库初始化完成')

@DBmanager.command

def migrate():

print('数据库迁移成功')

分开‘models’以及解决循环引用:

分开models的目的:为了让代码更加方便的管理

如何解决循环引用:把‘db’放在一个单独的文件中,切断循环引用的线条就可以了

# models_sep.py

from flask import Flask

from models import Article

from exts import db

# models.py

from exts import db

class Article(db.Model):

pass

# exts.py

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

db.init_app(app)

Flask-Migrate的介绍与安装

介绍:因为采用db.create_all在后期修改字段的时候,不会自动的映射到数据库中,必须删除表,然后重新运行db.create_all才会重新映射,这样不符合我们的需求。因此flask—migrade就是为了解决这个问题,它可以在每次修改模型后,将修改的内容映射到数据库中

安装:进入虚拟环境使用一下命令安装:

pip install flask-migrate

使用‘flask-migrate’必须借助‘flask-script’,这个包的‘MigrateCommand’中包含的所有与数据库相关的命令

‘flask-migrate’相关的命令:

python manager.py db init:初始化一个迁移脚本环境,只需要执行一次

python manager.py migrate:将模型生成迁移文件,只要模型更改了,就需要执行一边这个命令

python manager.py db upgrade:将迁移文件真正的映射到数据库中,每次运行了migrate命令后,就要运行此命令

注意点:需要映射到数据库的模型,都要导入到manager.py中,如果没有导入,就不会映射到数据库中

manager.py相关代码:

from flask_script import Manager

from migrate_demo import app

from flask_migrate import Migrate,MigrateCommand

from exts import db

from models import Article

# 模型 -> 迁移文件 -> 表

# init

# migrate

# upgrate

manager = Manager(app)

# 1. 要使用Flask-migrate,必须要绑定app和db

migrate = Migrate(app,db)

# 2. 把MigrateCommand命令添加到manager中

manager.add_command('db',MigrateCommand)

if __name__ == '__main__':

manager.run()

session和cookie操作

cookie的相关内容:

cookie出现的原因:在网站中,http请求是无状态的。这就是说即使第一次和服务器连接并且登录成功后,第二次请求服务器依然不能知道当前请求的是哪个用户。cookie的出现就是为了解决这一问题,第一次登录后,服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地。当用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪一个了

如果服务器返回了cookie给浏览器,那么浏览器再次请求相同的服务器的时候,就会自动的吧cookie发送给服务器,这个过程用户不需要处理

cookie是保存在浏览器中的,相对的是浏览器

session的相关内容:

session介绍:session和cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie是存储在本地浏览器,而session存储在服务器。存储在服务器的数据会更加安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但是服务器发展至今,一些session信息还是绰绰有余的

使用session的好处:

敏感数据不是直接发送回浏览器,而是发送回一个session_id,服务器将session_id和敏感数据做一个映射存储在session(服务器上)中,更加安全

session可以设置过期时间,也保证了用户的账号安全

Flask中的session工作机制

flask中session机制是:把敏感数据经过加密后放入session中,然后再把session存放到cookie中。下次请求的时候,再从浏览器发送过来的cookie中

读取session,然后从session中读取敏感数据并进行解密,最终获取到用户数据

flask的这种session机制,可以节省服务器的开销,因为把所有的信息都存储到了客户端(浏览器)

安全是相对的,把session放到cookie中,经过加密也是比较安全的

Flask中操作session

使用session需要从flask中导入session,以后所有和session相关的操作都是通过这个变量来的

使用session需要设置‘SECRET_KEY’用来加密,并且这个‘SECRET_KEY’如果在每次服务器启动后都变化的话,那么之前的session就不能再通过当前这个‘SECRET_KEY’进行解密了

操作session的时候和操作字典相同

添加:session['username']

删除:session.pop('username')或者del session['username']

获取:session.get('username')

清除所有session:session.clear()

设置session的过期时间

如果没有指定session的过期时间,那么默认是浏览器关闭后就自动结束

如果设置了session的permanent属性为True,那么过期时间默认为31天

可以通过设置:app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)来更改过期时间

装饰器

装饰器实际上就是一个函数,有两个特别之处

参数是一个函数

返回值是一个函数

装饰器的使用是通过@符号,放在函数的上面

装饰器中定义的函数,要使用args,*kwargs两个参数组合

需要使用functools.wraps在装饰器中的函数上把传进来的函数进行一个处理,这样就不会丢失其原来name等属性

from functools import wraps

def my_log(func):

@wraps(func)

def wrapper(*args, **kwargs):

print('hello world!')

func(*args, **kwargs)

return wrapper

@my_log

def run():

print('run')

@my_log

def add(a, b):

c = a + b

print('c = %s' % c)

run()

add(1, 3)

print(run.__name__)

知识点补充

get请求和post请求

get请求

使用场景:如果只对服务器获取数据,并没有对服务器产生任何影响,那么这时候使用get请求

传参:get请求传参是放在url中,并且是通过'?'的形式来指定key和value的

post请求

使用场景:如果要对服务器产生影响,那么使用post请求

传参:post请求传参不是放在url中,是通过‘form data’的形式发送给服务器的

get和post请求获取参数

get请求是通过flask.request.args来获取的

post请求是通过flask.request.form来获取的

post请求在模版中要注意:

input标签中要写name来标示这个value的key,方便后台获取

在写form表单的时候,要指定method='post',并且要指定action="{{ url_for('login') }}"

示例代码

用户名:
密码:

保存全局变量的g属性(g:global)

g对象是专门用来保存用户的数据的

g对象在一次请求中,代码所有的地方都是可以使用的

钩子函数(hook)

before_request:

在请求之前执行

是在视图函数执行之前执行的

这个函数只是一个装饰器,它可以把需要设置为钩子函数的代码放到视图函数执行之前执行

代码示例:

@app.before_request

def my_before_request():

if session.get('username'):

g.username = session.get('username')

context_processor:

上下文处理器应该返回一个字典,字典中的‘key’会被模版当作变量来渲染

上下文处理器中返回的字典,在所有页面中都是可用的

被这个装饰器修饰的钩子函数,必须要返回一个字典,即使为空也要返回

代码示例:

@app.context_processor

def my_context_processor():

return {'username':'Jason'}

实战演练

项目结构搭建

zlktqa.py:主app文件

config.py:配置文件,设置数据库、密钥、debug等等

exts.py:解决循环引用

manager.py:flask_script命令应用

models.py:分开models

导航条构建

BootCDN导入jQuery

head标签中引入bootstrp的css、jquery和js文件

父模版抽离

{% extends 'base.html' %}

{% block title %}首页{% endblock %}

{% block main %}这是首页{% endblock %}

登录页面完成和注册页面完成

pass

用户模型创建

创建模型User

class User(db.Model):

__tablename__ = 'user'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

telephone = db.Column(db.String(11), nullable=False)

username = db.Column(db.String(50), nullable=False)

password = db.Column(db.String(100), nullable=False)

进入虚拟环境,利用flask-script创建数据库表

python manage.py db init

python manage.py db migrate

python manage.py db upgrade

注册功能完成

注册功能未判断输入是否为空以及是否符合相应格式

密码在数据库中为明文

登录功能完成

待完善

登录和注销状态切换

利用钩子函数context_processor

发布问答界面完成

登录限制

在未登录状态下,访问发布问答页面时,要登录

from functools import wraps

from flask import session, redirect

# 登录限制的装饰器

def login_required(func):

@wraps(func)

def wrapper(*args, **kwargs):

if session.get('user_id'):

return func(*args, **kwargs)

else:

return redirect('login')

return wrapper

# 发布问答

@app.route('/question/')

@login_required

def question():

if request.method == 'GET':

return render_template('question.html')

else:

pass

发布问答功能完成

# 发布问答

@app.route('/question/', methods=['GET', 'POST'])

@login_required

def question():

if request.method == 'GET':

return render_template('question.html')

else:

title = request.form.get('title')

content = request.form.get('content')

question = Question(title=title, content=content)

user_id = session.get('user_id')

user = User.query.filter(User.id == user_id).first()

question.author = user

db.session.add(question)

db.session.commit()

return redirect(url_for('index'))

密码保护

from exts import db

# 导入转换密码需要的库

from werkzeug.security import generate_password_hash, check_password_hash

# 用户模型

class User(db.Model):

__tablename__ = 'user'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

telephone = db.Column(db.String(11), nullable=False)

username = db.Column(db.String(50), nullable=False)

password_hash = db.Column(db.String(255), nullable=False)

# 定义函数,需要用属性时,可以用函数代替

@property

def password(self):

return self.password_hash

# 转换密码为hash存入数据库

@password.setter

def password(self, row_password):

self.password_hash = generate_password_hash(row_password)

# 检查密码

def check_password(self, row_password):

return check_password_hash(self.password_hash, row_password)

# 登录

@app.route('/login/', methods=['GET', 'POST'])

def login():

if request.method == 'GET':

return render_template('login.html')

else:

telephone = request.form.get('telephone')

password = request.form.get('password')

user = User.query.filter(User.telephone == telephone).first()

if user:

if user.check_password(password):

session['user_id'] = user.id

session.permanent = True

return redirect(url_for('index'))

else:

return u'密码错误!'

else:

return u'用户不存在,请注册后登录!'

# 注册

@app.route('/regist/', methods=['GET', 'POST'])

def regist():

if request.method == 'GET':

return render_template('regist.html')

else:

telephone = request.form.get('telephone')

username = request.form.get('username')

password_1 = request.form.get('password_1')

password_2 = request.form.get('password_2')

# 手机号码验证,如果被注册,就不能再注册了

user = User.query.filter(User.telephone == telephone).first()

if user:

return u'改手机号已被注册,请更换手机号码!'

else:

# password_1和password_2要一样才可以

if password_1 != password_2:

return u'两次密码不一样,请核对后再填写!'

else:

user = User(telephone=telephone, username=username, password=password_1)

db.session.add(user)

db.session.commit()

# 如果注册成功,就让页面跳转到登录界面

return redirect(url_for('login'))

定时任务Celery

安装celery

pip install celery

通过Homebrew安装消息代理Redis

brew install redis

通过指令redis-server启动Redis(关闭redis:redis-cli shutdown)

通过终端进入celery文件所在目录,执行以下命令开启工作池

celery -A celery_task worker --loglevel=info

celery_task代码如下所示

#!/usr/bin/python

# -*- coding: UTF-8 -*-

from celery import Celery

from celery import platforms

from crawler import getdata

import datetime

import time

# 用于开启root也可以启动celery服务,默认是不允许root启动celery的

platforms.C_FORCE_ROOT = True

# 创建一个celery实例,传递进去的第一个参数必须是本文件的文件名celery,指定broker为本机redis6380服务

celery = Celery('celery_task', broker='redis://localhost:6379/0')

@celery.task

def task(h=1, m=0):

while True:

while True:

now = datetime.datetime.now()

if now.hour == h and now.minute == m:

break

time.sleep(60)

getdata()

print('执行完毕!')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值