Python之flask基础

news2024/11/18 23:48:51

文章目录

    • 入门小案例及认识路由
      • 小总结
    • 配置文件
    • 路由系统
      • 路由支持正则
    • cbv (用的比较少)
    • 模板
      • 渲染变量及循环
    • 请求响应
    • pipreqs(找当前项目依赖的包)
    • 闪现(flash)
    • 请求扩展(类似中间件)
    • 猴子补丁
    • 蓝图(blueprint)
    • threading.local
    • g对象的使用
    • flask-session
    • 数据库连接池
    • wtforms(forms组件)
    • 信号
    • flask-script(制定命令)
    • SQLAlchemy
    • 一对多关系与多对多关系
    • 基于scoped_session实现线程安全
    • orm增删改查
    • flask-migrate

flask中文网: https://flask.net.cn/

入门小案例及认识路由

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
	return "hello world"

if __name__ == '__main__':
	app.run()
from flask import Flask,request,render_template,redirect

app = Flask(__name__)

@app.route("/hello")
def index():
	# 当前请求地址,当前请求携带过来的数据
	print(request.path)
	return "hello world"

@app.route("/")
def index():
	# html模板要建在templates文件夹下
	return render_template("index.html")

if __name__ == '__main__':
	app.run()
from flask import Flask,request,render_template,redirect,session,url_for

app = Flask(__name__)
app.debug = True
# 如果使用session,必须配置secret_key 
app.secret_key ='sdfsdfsdfsdf' 

USERS = {
	1:{'name':'张三','age':18,'gender' :'男','text':'道路千万条'},
	2:{'name':'李四','age':28,'gender':'男','text' :'安全第一条'}3:{'name':'王五','age':18,'gender':'女','text':'行车不规范'},

@app.route('/detail/<int:nid>',methods=['GET']) 
def detail(nid):
	user = session.get('user_info')
	if not user:
		return redirect('/login')
	info = USERS.get(nid)
	return render_template('detail.html',info=info)
	
@app.route('/index',methods=['GET'])
def index():
	user = session.get('user_info')
	if not user:
		# return redirect( /login )
		url = url_for('11')
		return redirect(url)
	return render_template('index.html',user_dict=USERS)

@app.route('/login',methods=['GET','POST'],endpoint='11')
def login():
	if request.method == "GET":
		return render_template('login.html')
	else:
	# request.query_string
	user = request.form.get('user')
	pwd = request.form.get('pwd')
	if user=='cxw' and pwd=='123':
		session['user_info'] = user
		return redirect('http://www.baidu.com')
	return render_template('login. html',error="用户名或密码错误")


if __name__ == '__main__':
	app.run()
//login.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<h1>用户登录</h1>
	<form method='post'>
		<input type="text" name='user'>
		<input type="text" name='pwd'>
		<input type="submit" value='登录'> {{error}}
	</form>
</body>
</html>		
//detail.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<h1>详细信息 {{info.name}}</h1>
	<div>
		{{info.text}}
	</div>
</body>
</html>		
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<table>
		{% for k,v in user_dict.items() %} 
		<tr>
			<td>{{k}}</td>
			<td>{{v.name}}</td>
			<td>{{v['name']}}</td>
			<td>{{v.get('name')}}</td>
			<td><a href='/detail/{{k}}'}*>查看详细</a></td>
		</tr>
	</table>
</body>
</html>		

小总结

@app.route('/login',methods=['GET','POST'],endpoint='11')
-第一个参数是路径
-methods=['GET','POST'],请求方式
-endpoint='11',别名,如果不写,使用函数名作为别名
路由的本质: self.add_url_rule
# 另一种路由注册方式
def xxx():
	return 'xxx'
app.add_url_rule('/xxx',view_func=xxx)

配置文件

from flask import Flask

app = Flask(__name__)
#第一种方式
# app的配置文件全在config字典中,但是有一些常用的,比如debug, 会直接提到app这一层
#app.debug=True
#app.config['DEBUG'] = False

#第二种方式
#app.config.from_pyfile("seting.py")

#第三种方式
app.config.from_object("mysettings.TestingConfig")


@app.route("/")
def index():
	return "hello world"

if __name__ == '__main__':
	app.run()
	
# SECRET_KEY:如果使用session,必须配置
# SESSION_COOKIE NAME: cookie名字
# 数据库地址,端口号,也要放到配置文件中,但是不是的置的参数

# flask内 置session如何实现的? 
	-通过SECRET KEY加密以后,当做cookie返回给浏览 器
	-下次发送请求,携带cookie过来,反解,再放到session中

```python
# seting.py
DEBUG=True
# mysettings.py
class Config(object) :
	DEBUG = False
	TESTING = False
	DATABASE LURI ='sqlite://:memory:'

class TestingConfig(Config): # 测试阶段
	DEBUG = True
	TESTING = False
	DATABASE URI ='sqlite://:memory:'

class DevelopmentConfig(Config): # 开发阶段
	DEBUG = False
	TESTING = False
	DATABASE URI ='sqlite://:memory:'

路由系统

基本使用请见上第一小节

# 基本使用
@app.route('/detail/<int:nid>',methods=['GET'], endpoint='detail')

转换器

DEFAULT_CONVERTERS = {
	'default': UnicodeConverter,
	'string': UnicodeConverter,
	'any': Anyconverter,
	'path': Pathconverter,
	'int': IntegerConverter,
	'float': FloatConverter,
	'uuid': UUIDConverter,
}
@app.route和app.add_url_ rule 参数:
rule,URL规则
view_func,视图函数名称
defaults = None, 默认值,当URL中无参数, 函数需要参数时,使用defaults = {'k': 'v'} 为函数提供参数
endpoint = None, 名称, 用于反向生成URL,即: url_for('名称')
methods = None,允许的请求方式,如: ["GET", "POST"]
#对URL最后的/符号是否严格要求,默认严格,False, 就是不严格
strict_slashes = None
#重定向到指定地址
redirect_to = None ,
	@app. route(' /index/<int:nid>',redirect_ to= ' /home/ <nid> ')
#子域名访问
subdomain = None

路由支持正则

#1写类,继承BaseConverter
#2注册: app.url_map.converters['regex'].RegexConverter
#3使用: @app.route('/index/<regex("\d+"):nid>")正则表达式会当作第二个参数传递到类中
from flask import Flask,vlews,url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)

class RegexConverter(BaseConverter):
	#自定义URL匹配正则表达式
	def __init__(self, map, regex):
		super(RegexConverter, self).__init__(map)
		self.regex=regex
	def to_python(self, value):
		#路由四配时,匹配成功后传递给视图正数中参数的值
		return int(value)
	def to_url(self, value):
		#使用ur1_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
		val=super(RegexConverter, self).to_ url(value)
		return val

#添加到flask中
app.url_map.converters['regex']=RegexConverter
@app.route('/index/<regex("\d+"):nid>')
def index(nid):
	print(url_for("index", nid='888'))
	return 'Index'
if __name__ == '__main__':
	app.run()

cbv (用的比较少)

from flask import Flask
from flask import views

app = Flask(__name__)

#class IndexView(views.View):
#	methods = ['GET']
#	# decorators = [auth,]
#	def dispatch_request(self):
#		print('Index')
#		return 'Index!'

def auth(func):
	def inner(*args,**kwargs):
		print('before')
		result = func(*args,**kwargs)
		print('after')
		return result
	return inner

class IndexView(views.MethodView):
	methods = ['GET'] #指定运行的请求方法
	#登录认证装饰器加在哪?
	decorators = [auth, ] #加多 个就是从上往下的效果
	def get(self):
		return "我是get请求"
	def post(self):
		return "我是post请求"

#路由如何注册?
# IndexView.as_view('index'),必须传name
app.add_url_rule('/index',view_func=IndexView.as_view('index'))

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


#用的比较少
#继承views.MethodView, 只需要写get, post, delete方法
#如果加装饰器decorators = [auth, ]
#允许的请求方法methods = ['GET']

模板

渲染变量及循环

<!IDOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<h1>用户列表</h1>
	<table>
	{% for k,v in user_dict.items() %}
		<tr>
			<td>{{k}}</td>
			<td>{{v.name}}</td>
			<td>{{v['name']}}</td>
			<td>{{v.get("nane")}}</td>
			<td><a href="/detail/{{k}}">查看详细</a></td>
		</tr>
		{% endfor %}
	</table>
</body>
</html>

请求响应

from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_response,jsonify

app=Flask(__name__)
@app.route('/login.html', mnethods=['GET','POST'])
def login():
	#请求相关信息
	# request.method 	提交的方法
	# request.args 	get请求提及的数据
	# request.form 	post请求提交的数据
	# request.values 	post和get提交的数据总和
	# request.cookies	客户端所带的cookie
	# request.headers	请求头
	# request.path 	不带域名,请求路径
	# request.full_path	不带域名 ,带参数的请求路径
	# request.script_root
	# request.url 	带域名带参数的请求路径
	# request.base_url	 带域名请求路径
	# request.url_root 	域名
	# request.host_url 	域名
	# request.host		127.0.0.1:500
	# request.fles
	# obj = request.flles["the_flle. name"]

	
	# 响应对象
	# 响应相关信息
	#return '字符串'
	# return render_template( html模板路径,**{})
	# return redirect('/index. html')
	#对着django, JsonResponse
	# return jsonify({'k1':' v1'})

	aa='hello world'
	res=make_response(aa)
	res.set_cookie('xxx','1qz')
	res.headers['X-Something'] ='A value'
	return res

	# response = make_response(render_template( 'index.html'))
	# response是flask.wrappers.Response类型
	# response.delete_cookie('key')
	# response.set_cookie('key','value')
	# response.headers['X-Something'] ='A value'
	# return response
	# return 'hello'

pipreqs(找当前项目依赖的包)

pip install pipreqs

在项目根目录下执行命令:(生成requirements.txt文件)

pipreqs ./ --encoding=utf-8

执行以下命令安装所有组件:

pip install -r requirements.txt

闪现(flash)

-设置:flash(‘aaa’ )
-取值: get_flashed_message()
-假设在a页面操作出错,跳转到页面,在b页面显示a页面的错误信息

from flask import Flask, request, jsonify, make_response, session, flash

app=Flask(__name__)
app.debug=True
app.secret_key='dcdsjhcksjsdhshd'
@app.route('/',methods=['GET', 'POST'])
def index():
	flash('lqz-nb') #往某个位置放值
	return 'hello'

@app.route('/order',methods=['GET','POST'])
def order():
	return get_flashed_messages() #从某个位置取出来

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

请求扩展(类似中间件)

from flask import Flask, request, jsonify, make_response, session, flash,redirect

app=Flask(__name__)
app.debug=True
app.secret_key='dcdsjhcksjsdhshd'

#请求来了就会触发,类似于django的process_ request,如果有多个,顺序是从上往下
@app.before_request
def before(*args,**kwargs):
	print('请求来了执行我')
	if request.path=='/login':
		return None
	else:
		name=session.=get('user')
		if not name:
			return redirect('/login')
		else:
			return None

@app.route('/login',methods=['GET', 'POST'])
def index():
	session['user']='lqz'
	return 'login'

@app.route('/order',methods=['GET', 'POST'])
def index():
	return 'order'

#请求走了就会触发,类似fdjango的process. response,如果有多个,顺序是从下往上执行
@app.after_request
def after(response):
	print('我走了')
	return response

# 项目启动起来第一次会走, 以后都不会走了
@app.before_first_request
def first():
	print('可以做初始化操作')

# 每一个请求后都会走,即使发生错误
@app.teardown_request
def ter(e):
	print(e)
	print('可以记录错误日志')
	return '我错了'

@app.errorhandler(500)
def error_500(arg):
	return render_template('error. html',message='500错误')

@app.errorhandler(404)
def error_404(arg):
	return render_template('error.htm1',message='404错误') 

# 全局标签 html页面引用 {{sb(3,4)}}
@app.template_globa1()
def sb(a1, a2):
	return a1 + a2

# 全局过滤器 {{1|db(2,3)}}
@app.template_filter()
def db(a1, a2, a3):
	reture a1+a2+a3

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

猴子补丁

一个概念,面向对象理念

#有什么用?
#这里有一个比较实用的例子,
#很多用到import json,
#后来发现yjison性能更高,
#如果觉得把每个文件的import json改成import uison as json成本较高,
#或者说想测试一下uison替换是否符合预期, 只需要在入口加上:
#只需要在程序入口

import json
import ujson
def monkey_patch_json():
	json.__name__ ='ujson'
	json.dumps = ujson.dumps
	json.loads = ujson.loads
monkey_patch_json()
aa= json.dumps({'name':'1qz','age':19})
print(aa)


#协程,单线程下实现并发
# from gevent import monkey;monkey.patch_all()
import gevent 
import time
def eat():
	print('eat food 1')
	#time.sleep(2)
	gevent.sleep(2) # 没有用猴子补丁的时候用这个
	print(' eat food 2' )

def p1ay():
	print(' play 1') 
	#time.sleep(1)
	gevent.sleep(1) # 没有用猴子补丁的时候用这个
	print(' play 2' ) 
g1= gevent.spawn(eat)
g2 gevent.spawn(play)
gevent.joinall([g1, g2])
print('主')

蓝图(blueprint)

1没有蓝图之前前,都是单文件
2有了蓝图可以分文件
在这里插入图片描述
在这里插入图片描述
蓝图使用:

#第一步在app中注册蓝图,括号里是一个 蓝图对象
app.register_b1ueprint(user.us)
#第二步,在不同文件中注册路由时,直接使用蓝图对象注册,不用使用app了,避免了循环导入的问题
@account.route('/1ogin. htm1',methods=['GET', "POST"])
中小型项目目录划分:
项目名字:
-pro_ flask文件夹
-templates
	login.htm1
-statics
	code.png
-views
	blog.py
	account.py
	user.py
-__init__.py
-run.py

threading.local

#不用1ocal
from threading import Thread
import time
1qz = -1
def task(arg):
	global 1qz 
	1qz = arg
	# time.sleep(2)
	print(1qz)
for i in range(10) :
	t =Thread(target=task,args=(i,))
	t. start()
from threading import Thread
from threading import 1ocal
import time
from threading import get_ident
#特殊的对象
1qz = 1oca1()
def task(arg):
	#对象.val = 1/2/3/4/5
	1qz.value = arg
	time.sleep(2)
	print(1qz.value)
for i in range (10):
	t = Thread(target=task,args=(i,)) 
	t.start()
from threading import get_ident, Thread
inport time
storage = {}
def set(k,v):
	ident = get_ident()
	if ident in storage:
		storage[ident][k] = v
	else:
		storage[ident] = {k:v} 
def get(k):
	ident = get_ident()
	return storage[ident][k]
def task(arg):
	set('val',arg)
	v = get('val')
	print (v)
	
for i in range(10) :
	t = Thread(target=task, args=(i,))
	t. start()
# 面向对象版
from threading import get_ident,Thread
import time
class Local(object):
	storage = {}
	def set(self, k, v):
		ident = get_i dent()
		if ident in Local.storage:
			Loca1.storage[ident][k] = v
		else:
			Local.storage[ident] = {k: v}
	def get(self, k):
		ident = get_ident()
		return Local.storage[ident][k]
obj = Local()
def task(arg):
	obj.set('va1', arg)
	v = obj.get('val')
	print(v)
for i in range(10):
	t =Thread(target=task, args=(i,)) 
	t. start()
# 最终版
from threading import get_ ident,Thread
import time
class Local(object):
	# storage = {} 类的storage 
	def __init__(self):
		object.__setattr__(self,'storage',{})
	def __setattr__(self, k,v):
		ident = get_ident()
		if ident in Local.storage:
			Local.storage[ident][k] = v
		else:
			Local.storage[ident] = {k: v}
	def __getattr__(self, k):
		ident = get_ident()
		return Local.storage[ident][k]
obj = Local()
obj2 = Local()
def task(arg):
	obj.val = arg
	print(obj.va1)
for i in range(10):
	t = Thread(target=task ,args=(i,))
	t. start()

g对象的使用

#1 g是一个全局变量,在当前请求中可以放值,取值
#2 g和session有什么不同? session只要是这个人,没有删除session,每次请求都会有值
# session对象是可以跨request的, 只要session还未失效, 不同的request的请求会获取到同一个session, 但是g对象不是,g对象不需要管过期时间,请求次就g对象就改变了一次,或者重新赋值了一次

flask-session

作用:将默认保存的签名cookie中的值保存到redis/memcached/file/Mongodb/SQLAlchemy
安装: pip3 install flask-session
使用1:

from flask import Flask, session
from flask_session import RedissessionInterface
import redis

app = Flask(__name__)
conn=redis.Redis(host='127.0.0.1',port-6379) 
#use_signer是否对key签名
app.sesslon_interface=Redi ssessionIntenface(conn,key_prefix='1qz')

@app.route('/')
def hello_world():
	session['name']='1qz'
	return "Hello Horld!"
	
if __name__== '__main__':
	app.run()

使用2:(本质跟上面一样)

from redis import Redis
from flask.ext.session import Session

app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
Session(app)

问题:设置cookie时, 如何设定关闭浏览器则cookie失效。

response.set_cookie('k','v',exipre=None) #这样设置即可
#在session中设置
app.session_interface=RedisSessionInterface(conn,key_ prefix='1qz',permanent=False)
# 一般不用,我们一般都设置超时时间,多长时间后失效

问题: cookie默认超时时间是多少?如何设置超时时间

#源码expires = self.get_expiration_time(app,session)
'PERMANENT_SESSION_LIFETIME':
timedelta(days=31),这个配置文件控制

数据库连接池

【参考】https://www.cnblogs.com/liuqingzheng/articles/9006055.html

pymsq|链接数据库

import pymysql

conn= pymysql.connect(host='127.0.0.1', port=3306, user='root',passwd='123456', db='s8day127db')
cursor = conn.cursor(cursor=pymysql.cursors=.DictCursor)
# cursor . execute("select id,name from users where name=%s and pwd=%s",['1qz','123',])
cursor.execute("select id,name from users where name=%(user)s and pwd=%(pwd)s" ,{'user':'1qz','pwd':'123'})
obj = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
print(obj)

wtforms(forms组件)

1校验数据
2渲染标签

from wtforms import Form
from wtforms.fields import simple 
from wtforms import validators
from wtforms import widgets
app = Flask(__name__,template_folder='templates')
app.debug = True

class LoginForm(Form):
	#字段(内部包含正则表达式)
	name = simple.StringField(
		label='用户名',
		validators=[ 
			validators.DataRequired(message='用户名不能为空.'),
			validators.Length(min=6, max=18,message='用户名长度必须大于% (min)d且小于% (max)d')
		],
		widget=widgets.TextInput(), #页面上显示的插件
		render_kw={'class':'form-control' }
	)
	#字段(内部包含正则表达式)
	pwd = simple.PasswordField( 
		label='密码',
		validators= [ 
			validators.DataRequired (message='密码不能为空'),
			validators.Length(min=8, message='用户名长度必须大于%(min)d'),
		validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$ !%*?&]{8,}",
			message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符')
		],
		widget=widgets.PasswordInput(),
		render_kw={'class':'form-control'}
	)

@app.route('/login',methods=["GET",'POST'])
def login():
	if request.method =='GET':
		form = LoginForm()
		return render.template('login.html',form=form)
	else:
		form = LoginFor(formdata=request.form) 
		if form.validate():
			print('用户提交数据通过格式验证,提交的值为:',form.data)
		else:
			print(form.errors)
		return render_template('login. html',form=form)

if __name__=='__main__':
	app.run()
<!DOCTYPE html>
<html lang=" en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
<h1>登录</h1>
<form method="post" >
	<p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>
	<p>{{form.pwd.label1}} {{form.pwd}} {{form.pwd.errors[0]}}</p>
	<input type=" submit" value="提交">
</form>
</body>
</html>

信号

Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一一些用户行为
安装: pip3 install blinker

内置信号:

request_started =_signals.signal('request-started')
#请求到来前执行
request_finished = _signals.signal('request-finished')
#请求结束后执行
before_render.template =_signals.signal('before -render-template') # 模板渲染前执行
template_rendered =_signals.signal('template-rendered')
#模板渲染后执行
got_request_exception =_signals.signal('got-request-exception')
#请求执行出现异常时执行
request_tearing.down =_signals.signal('request-tearing-down')
#请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down =_signals.signal('appcontext-tearing-down')#应用上下文执行完毕后自动执行(无论成功与否)
appcontext_pushed =_signals.signal('appcontext -pushed')
#应用上下文push时执行
appcontext_popped =_signals.signal('appcontext-popped')
#应用上下文pop时执行
message_flashed =_signals.signal('message-flashed')
#调用flask在其中添加数据时,自动触发
from flask import Flask,signals
app=Flask(__name__,static_url_path='/static',static_folder='static',template folder='templates')

#第一步:写一个函数(触发果些动作)
#往信号中注册函数
def func(*args,**kwargs): 
	print('触发信号',args, kwargs)

#第二步:函数跟内置信号绑定
signals.request_started.connect(func)

@app.route("/")
def index():
	return 'xxx'
	
if __name__='__main__':
	app.run()

######内置信号的使用
##第一步写一个函数(触发某些动作)
#往信号中注册函数
def func(*args, ** kwargs):
	print(args[0]) # 当前app对象
	print('触发信号' ,args,kwargs)
#第二步:函数跟内置信号绑定
signals.request_started.connect(func)

####自定义信号的使用
#自定义信号
##第一步:定义一个信号
# xxxxx=_ signals.signal('xxxxx')
##第二步:定义一个函数
# def func3(*args, **kwargs):
# 	import time
#	time. sleep(1)
#	print('触发信号' ,args,kwargs)
# #第三步:信号跟函数绑定
# xxxxx.connect(func3)
#第四步:触发信号
xxxxx. send(1,k='2')

flask-script(制定命令)

1模拟出类似django的启动方式: python manage. py runserver
2 pip install flask-script

在这里插入图片描述
自定制命令:

@manager.command
def custom(arg):
	"""
	自定义命令
	python manage.py custom 123
	:param arg:
	:return:
	"""
	print(arg)
@manager.option('-n', '--name', dest= 'name')
#@manager.option('-u', '--url', dest='url')
def cnd(name, url):
	"""
	自定义命令(-n也可以写成--name)
	执行: python manege.py cnd -n 1qz -u http://www.oldboyedu.com
	执行: python marlage.py cmd --name 1qz --url http://ww.oldboyedu.com
	:param name:
	:param url:
	:return:
	"""
	print(name, url)

#有什么用?
#把excel的数据导入数据库,定制个命令,去执行
# python manage.py insertdb -f xxx.exc1 -t aa

SQLAlchemy

pip install sqlalchemy

1执行原生sql (不常用)

import time
import threading
import sqlalchemy
from sqlalchemy import create.engine
from sqlalchemy.engine.base import Engine

engine=create_engine(
	"mysql+pymysq1://root:123456@127.0.0.1:3306/test?charset=utf8" ,
	max_overflow=0,# 超过连接池大小外最多创建的连接
	pool_size=5, #连接池大小
	pool_timeout=30# 池中没有线程最多等待的时间,否则报错
	pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收 (重器)
	
def task(arg):
	conn = engine.raw_connection()
	cursor = conn.cursor()
	cursor.execute(
	"select * from app01_book")
	result = cursor.fetchall()
	print(result)
	cursor.close()
	conn.close()

2 orm使用
models,py

import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,Integer,String,Text,ForeignKey,DateTime,UniqueConstraint,Index

Base=declarative_base()

class Users(Base):
	__tablename__ = 'users' #数据库表名称
	id = Column(Integer, primary key=True) # id主键
	name = Column(String(32),index=True,nullablemFalse) # name列, 索引,不可为空
	# email = Column(String(32), unique=True)
	#datetime.datetime.now不能加括号,加了括号,以后永远是当前时间
	# ctime = Column(DateTime, default=datetime.datetime.now)
	# extra = Column(Text, nullable=True)
	
	__table_args__ = (
		# UniqueConstraint('id', 'name', name='uix_ id_ name'), #联合唯一
		# Index('ix_id_name', ”name', 'email'), #索引
	)

def init_db():
	"""
	根据类创建数据库表
	: return:
	"""
	engine = create_engine(
		'mysql+pymysql://root:123456@127.0.0.1:3306/ aaa?charset-utf8',
		max_overflow=0, # 超过连接池大小外最多创建的连接
		pool_size=5, # 连接池大小
		pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
		pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收 (重置)
	)
	#通过engine对象创建表
	Base.metadata.create_all(engine)

#删除表
def drop_table():
	#创建engine对象
	engine = create_engine(
		"mysql+pymysql://root:123@127. 0. 0. 1:3306/ aaa?charset=utf8",
		max_overflow=0,# 超过连接池大小外最多创建的连接
		pool_size=5, #连接池大小
		pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
		pool_recycle=-1 #多久之后对线程池中的线程进行一-次连接的回收(重置)
	#通过engine对象删除所有表
	Base.metadata.drop_all(engine)

if __name__ = '__main__':
	create_table()
	# drop_table()

app.py

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create engine
from models import Users
#"mysql+pymysq1://root@127.0.0.1:3306/aaa"
engine = create.engine("mysq1+pymysql://root:123456@127 .0.0.1:3306/aaa", max_overf1ow=0, pool_size=5)
Connection = sessionmaker(bind=engine)

#每次执行数据库操作时,都需要创建一个Connection
con = Connection()

#########执行ORM操作#############
obj1 = Users(name="1qz")
con.add(obj1)
#提交事务
con.commit()
#关闭session,其实是将连接放回连接池
con.close()

一对多关系与多对多关系

#一个Hobby可以有很多人喜欢
#一个人只能由一个Hobby
class Hobby (Base):
	__tablename__=' hobby'
	id = Column(Integer, primary_key= True)
	caption = Column(String(50),default='篮球') 
class Person(Base):
	__tablename__='person'
	nid = Column(Integer, primary_key=True)
	name = Column(String (32),index=True,nullable=True)
	# hobby指的是tablename而不是类名,uselist=False
	#一对多的关系,关联字段写在多的一”方
	hobby_id = Column(Integer, ForeignKey('hobby.id'))
	#跟数据库无关,不会新增字段,只用于快速链表操作
	#类名,backref用于反向查询
	#hobby=relationship('Hobby',backref='pers')
# 多对多关系
class Boy2Girl(Base):
	__tablename__ = 'boy2girl'
	id = Column(Integer, primary_key=True,autoincrement=True)
	girl_id = Column(Integer, ForeignKey('girl.id')
	boy_id = Column(Integer, ForeignKey('boy.id'))

class Girl(Base):
	__tablename__ = "girl"
	id = Column(Integer, primary_key=True)
	name = Column(String(64),unique=True,nullable=False)

class Boy(Base):
	__tablename__ = 'boy'
	id = Column(Integer, primary_key=True,autoincrement=True)
	hostname = Column(String(64), unique=True,nullable=False)
	#与生成表结构无关,仅用于查询方便,放在哪个单表中都可以
	servers = relationship('Girl', secondary= 'boy2girl', backref="boys")

基于scoped_session实现线程安全

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped.session
from models import Users
engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/s6", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)
"""
#线程安全,基于本地线程实现每个线程用同-个session
#特殊的: scoped_ session中有 原来方法的Session中的一下方法: 
public_ methods - (
	'__contains__' ,'__iter__','add', 'add_ all','begin', 'begin. nested',
	'close', 'commit', 'connection', 'delete','execute', 'expire',
	'expire_all', 'expunge', ' expunge_ all', 'flush', 'get. bind',
	'is_ modified', 'bulk_ save_ objects', 'bulk_ insert. mappings',
	'bulk_ update_ mappings ' ,
	'merge', 'query', 'refresh', 'rollback',
	'scalar'
)
"""
#scoped_session类并没有继承Session,但是却又它的所有方法
session = scoped_session(Session)
#共**.*.**.执行ORM操作共#.**.*.#
obj1 = Users(name="alex1")
session.add(obj1)
# 1制作engine 
engine = create_engine('mysql+pymysql://root: 123@127.0.0.1:3306/aaa',max_overflow=0, pool_size=5)
#2制造一个session类(会话)
Session = sessionmaker(bind=engine)
#得到一个类
# 3得到一个session对象(线程安全的session)
#现在的session已经不是session对象了
#为什么线程安全,还是用的local
session = scoped_session(Session)
# session=Session() #得到个session对 象
# conn=Session(
# 4创建一个对象
obj1 = User(name="lqz")
# 5把对象通过add放入
session.add(obj1)
#6提交
session.commit()

orm增删改查

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped.session
from models import User

engine = create_engine('mysql+pymysql://root: 123@127.0.0.1:3306/aaa',max_overflow=0, pool_size=5)

Session = sessionmaker(bind=engine)
session = scoped_session(Session)

###1批量添加
obj=User(name='xxx')
obj2=User(name='yyyy')
obj3=User(name='zzz')
session.add_all([obj, obj2, obj3])

###2简单删除(查到删除)
# res=session.query(User).filter_by(name='2008').delete()
res=session.query(User).filter(User.id>3).delete()
#影响1行
print(res)

##3修改
res=session.query(User).filter_by(id=1).update({'name': 'egon'})

###4基本查询操作
res=session.query(User).al1()
print(type(res))
res=session.query(User).first()
print(res)

# 执行原生sql
cursor = session.execute('insert into users(name) values (value)',params={"value":'1qz'})
print(cursor.lastrowid)

session.commit()
#并没有真正关闭连接,而足放回池中
session.close()

flask-migrate

离线脚本,创建表
详见代码

flask-migrate
python3 manage.py db init 初始化:只执行一次
python3 manage.py db migrate 等同于makemigartions
python3 manage.py db upgrade 等同于migrate
Flask-SQLAlchemy如何使用
1 from flask_sq1alchemy import SQLAlchemy
2 db = SQLA1chemy()
3 db.init_app(app)
4以后在视图函数中使用
	-db.session就是咱们讲的session

flask-migrate的使用(表创建,字段修改)
1 from flask_migrate import Migrate ,MigrateCommand
2 Migrate(app, db)
3 manager.add_command('db' ,MigrateCommand)

在这里插入图片描述
在这里插入图片描述

【参考】https://www.bilibili.com/video/BV11N411f7Ga
【参考】https://www.cnblogs.com/xiaoyuanqujing/category/1561311.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/388733.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】Redis集群之哨兵机制

【Redis】Redis集群之哨兵机制 文章目录【Redis】Redis集群之哨兵机制1. 哨兵的作用和原理1.1 哨兵的作用1.2 redis服务状态监控1.3 选举新master1.4 故障转移1.5 总结2. 搭建哨兵集群2.1 准备实例和配置2.2 启动2.3 测试3. RedisTemplate的哨兵模式1. 哨兵的作用和原理 1.1 哨…

1634_linux中把pdf拆分成独立的图片文件

全部学习汇总&#xff1a; GreyZhang/toolbox: 常用的工具使用查询&#xff0c;非教程&#xff0c;仅作为自我参考&#xff01; (github.com) 最近工作学习之中使用pdf的频次非常高&#xff0c;这种格式的通用性的确是不错。在目前的很多平台上都有很好用的软件。不过&#xff…

ios设备管理软件 2.16.9官网Mac/Windows下载电脑版功能介绍

imazing 2.16.9官网Mac/Windows下载电脑版是款针对苹果设备所打造的管理工具。iMazing为用户提供多种设备管理功能&#xff0c;每一位用户都能以自己的形式管理苹果设备。iMazing与苹果设备连接后&#xff0c;用户就可以轻松传输文件&#xff0c;浏览保存信息等。 应用介绍 i…

Zookeeper3.5.7版本——集群启动停止脚本

目录一、Zookeeper3.5.7集群部署&#xff08;linux环境-centos7&#xff09;二、3台服务器信息三、Zookeeper3.5.7集群启动停止脚本3.1、编写zk.sh脚本3.2、增加脚本执行权限3.3、执行Zookeeper 集群的zk.sh脚本四、执行脚本启动Zookeeper 集群五、执行脚本查看Zookeeper 集群状…

Lesson11---分类问题

11.1 逻辑回归 11.1.1 广义线性回归 课程回顾 线性回归&#xff1a;将自变量和因变量之间的关系&#xff0c;用线性模型来表示&#xff1b;根据已知的样本数据&#xff0c;对未来的、或者未知的数据进行估计 11.1.2 逻辑回归 11.1.2.1 分类问题 分类问题&#xff1a;垃圾…

SS-ELM-AE与S2-BLS相关论文阅读记录

Broad learning system for semi-supervised learning 摘要&#xff1a;本文认为&#xff0c;原始BLS采用的稀疏自编码器来生成特征节点是一种无监督学习方法&#xff0c;这意味着忽略了标注数据的一些信息&#xff0c;并且难以保证同类样本之间的相似性和相邻性&#xff0c;同…

CentOS 7.9汇编语言版Hello World

先下载、编译nasm汇编器。NASM汇编器官网如下图所示&#xff1a; 可以点图中的List进入历史版本下载网址&#xff1a; 我这里下载的是nasm-2.15.05.tar.bz2 在CentOS 7中&#xff0c;使用 wget http://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2下载…

用Python Flask为女朋友做一个简单的网站(附可运行的源码)

&#x1f31f;所属专栏&#xff1a;献给榕榕&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该专栏系为女友准备的&#xff0c;里面会不定时发一些讨好她的技术作品&#xff0c;感兴趣的小伙伴可以关注一下~&#x1f449;文章简介…

微信小程序原生开发功能合集四:复选框组件的封装

本章实现小程序复选框组件的封装,使用check及check-group组件实现复选框,封装数据加载过程,并自动实现数据解析及生成,实现相应方法。   另外还提供小程序开发基础知识讲解课程,包括小程序开发基础知识、组件封装、常用接口组件使用及常用功能实现等内容,具体如下:  …

k-Medoids 聚类系列算法:PAM, CLARA, CLARANS

前言 如果你对这篇文章可感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 kkk-Means 作为一种经典聚类算法&#xff0c;相信大家都比较熟悉&#xff0c;其将簇中所有的点的均值作为簇中心&#xf…

JavaScript- Map、Set、WeakMap、WeakSet、简单模拟Map

文章目录Map常见方法set常见方法WeakMapWeakSet如何实现一个Map?(简单模仿)Map Map是一种键值对的结构 常见方法 Map.prototype.set()Map.prototype.has()Map.prototype.get()Map.prototype.delete() set 常见方法 Set类似于数组&#xff0c;但是里面成员的值都是唯一的…

【Java】Spring MVC程序开发

文章目录Spring MVC程序开发1. 什么是Spring MVC&#xff1f;1.1 MVC定义1.2 MVC 和 Spring MVC 的关系2. 为什么学习Spring MVC&#xff1f;3. 怎么学习Spring MVC&#xff1f;3.1 Spring MVC的创建和连接3.1.1 创建Spring MVC项目3.1.2 RequestMapping 注解介绍3.1.3 Request…

OpenCV实战(12)——图像滤波详解

OpenCV实战&#xff08;12&#xff09;——图像滤波详解0. 前言1. 频域分析2. 低通滤波器3. 图像下采样3.1 使用低通滤波器下采样图像3.2 内插像素值4. 中值滤波器5. 完整代码小结系列链接0. 前言 滤波是信号和图像处理中的基本任务之一&#xff0c;其旨在有选择地提取图像的某…

【Linux】CentOS7操作系统安装nginx实战(多种方法,超详细)

文章目录前言一. 实验环境二. 使用yum安装nginx2.1 添加yum源2.1.1 使用官网提供的源地址&#xff08;方法一&#xff09;2.1.2 使用epel的方式进行安装&#xff08;方法二&#xff09;2.2 开始安装nginx2.3 启动并进行测试2.4 其他的一些用法&#xff1a;三. 编译方式安装ngin…

Angular快速入门

Angular1.框架背景2.Angular CLI2.1 安装2.2 主要特性2.3 创建module&#xff0c;component&#xff0c;service&#xff0c;class3.架构3.1 模块3.2 组件3.2.1 创建组件3.2.2 组件生命周期3.2.3 组件交互3.3 模板3.3.1 插值语法3.3.2 属性绑定3.3.3 条件判断3.3.4 循环语句3.3…

22. linux系统基础

递归遍历指定文件下所有的文件&#xff0c;而且你还可以统计一下普通文件的总个数&#xff0c;既然能统计普通文件&#xff0c;能统计其他文件吗&#xff1f;比如目录文件&#xff0c; 这个是main函数里面我们调用了 &#xff0c;这个checkdird这个函数&#xff0c;需要传递一个…

垃圾收集器以及三色标记

分代收集理论当前虚拟机的垃圾收集采用分代收集算法&#xff0c;只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代&#xff0c;这样我们就可以根据各个年代的特点选择合适的垃圾收集算法新生代:每次收集都会有大量对象(近99%)死去&#xff0c;所以可…

教资教育知识与能力中学教学

目录 3.1 教学概述 3.2 教学过程 3.3 教学原则*【简答/辨析重点】 3.4 教学方法 3.5 教学组织形式 3.6 教学工作基本环节 3.7 教学评价 3.1 教学概述 1、教学的意义【14/18辨析】 教学是传授系统知识、促进学生发展的最有效形式&#xff1b; 教学是学校进行全面发展教…

MSTP多域实验配置

目录 实验配置 配置MSTP MSTP参数修改 查看每个设备的生成树 配置MSTP安全 实验配置 放行相关Vlan MST1域内的交换机互联接口放行Vlan 30、40 MST2域内的交换机互联接口放行Vlan 10、20、40 MST1域和MST2域之间交换机互联端口放行Vlan 40 配置MSTP 全网交换机都开启MSTP&a…

【SpringMVC】springMVC介绍

参考资料 视频资料 03_尚硅谷_SpringMVC_SpringMVC简介_哔哩哔哩_bilibili 笔记资料 第一节 SpringMVC概述 (wolai.com)链接&#xff1a;https://pan.baidu.com/s/1A7BX2TNfbGTpYene4x3Mew 提取码&#xff1a;a8d5 一、SpringMVC简介 1、什么是MVC MVC是一种软件架构的思…