FLASK学习笔记

Flask 轻量级框架 WEB 框架
AJAX 在web中完成异步请求和响应
Django 重量级WEB框架

Python Web

1.静态网页 和 动态网页
1.静态网页 :无法与服务器做动态交互的网页
2.动态网页 :允许与服务器做动态加护的
2.WEB 与 服务器
1.WEB : 网页(HTML,CSS,JS)
2.服务器
能够给用户提供服务的机器就可以称为 服务器
1.硬件 与 软件
硬件 :一台主机
软件 :一个能够接受用户请求并给出响应的程序
1.APACHE
2.TOMCAT
3.IIS(Internet Information Service)
4.Nginx
2.作用
1.存储WEB上的信息
2.能够处理用户的请求(request)并给出响应(response)
3.执行服务器端程序
4.具备一定的安全功能
3.框架
1.什么是框架
框架是一个为了解决开放性问题而存在一种程序结构。
框架本身提供了一些最基本的功能。
我们只需要在基础功能上搭建自己的操作就可以了。
2.Python Web 框架
1.Flask - 轻量级
2.Webpy - 轻量级
3.Tornado - 异步框架
4.Django - 重量级框架
3.框架模式
1.MTV
M :Models,模型层,主要负责数据库建模、
T :Templates,模板层,用于处理用户的显示内容,如 html
V :Views,视图,处理与用户打交道的内容(请求和响应)
2.MVC
M :Models,模型层,主要负责数据库建模
V :Views,视图,处理用户的显示内容
C :Controller,控制器,用于与用户交互的部分内容(请求和响应)

		M  ---  M
		T  ---  V
		V  ---  C

4.Flask框架
1.什么是Flask框架
Flask是一个基于Python并且依赖于Jinja2模板引擎和Werkzeug WSGI服务的一个微型框架
WSGI :Web Server Gateway Interface(WEB服务网关接口)

	Flask是采用 MTV 的框架模式
2.安装 Flask
	1.查看已安装的Flask版本
		在 python 的交互模式中 :
			1. import flask
				没报错:已经安装了Flask,可以继续查看版本
				报错:没安装Flask
			2. flask.__version__
				已安装Flask的情况下,可以查看安装的版本
	2.安装Flask
		sudo pip3 install flask
		pip3 download flask
3.Flask 初始化
	见代码 ... ...

	练习:
		访问路径:http://localhost:5000/login :
			在网页中显示 :欢迎访问登录页面
		访问路径:http://localhsot:5000/register
			在网页中显示 :欢迎访问注册页面

5.Flask - 路由(route)
1.什么是路由
客户端发送请求给web服务器,web服务器再将请求发送给Flask程序实例
程序实例需要知道每个url请求所对应的运行代码是谁。所以程序中必须要创建一个 url 请求地址 到 python运行函数的一个映射。处理url和函数之间的关系的程序就是"路由"
2.路由的体现
在 Flask 中,路由是通过 @app.route 装饰器来表示的
1.路由的基本表示
# http://localhost:5000
@app.route('/')
def index():
return "xxx"

		# http://localhost:5000/admin/login
		@app.route('/admin/login')
		def admin_login():
			return 'xxx'
	2.带参数的路由
		路由中可以携带参数表示不同的数据
		http://localhost:5000/show/laowang
		http://localhost:5000/show/wangwc
		http://localhost:5000/show/laowang.gebi
		1.基本带参路由
			@app.route('/show/<name>')
			def show(name):
				name : 表示的就是从地址栏上传递过来的数据
				return 'xxx'
		2.带多个参数的路由
			http://localhost:5000/show/laowang/36
			@app.route('/show/<name>/<age>')
			def show(name,age):
				return 'xxx'
		3.指定参数类型的路由
			@app.route('/show/<name>/<int:age>')
			def show(name,age):
				name : 字符串
				age : 整数

			int: 类型转换器
			Flask 中所支持的类型转换器:
				类型转换器        作用
				缺省              字符串,不能有斜杠('/')
				int:              整型
				float:            浮点型
				path:             字符串,可以有斜杠('/')
	3.多 URL 的路由匹配
		为多个访问地址匹配同一个视图处理函数
		@app.route('/地址1')
		@app.route('/地址2')
		... ...
		def index():
			return ""

		练习:
			当访问路径是以下任何一个的时候:
				http://localhost:5000
				http://localhost:5000/index
				http://localhost:5000/数字
				http://localhost:5000/index/数字
			将程序交给 index() 视图处理函数
				判断路由中到底有没有数字传递进来,
				如果有
					响应 :您当前看的页数为 :xxx
				如果没有:
					响应 :您当前看的页数为 :1
	4.路由中设置 HTTP 请求方法
		Flask路由也允许设置对应的请求方法(post/get),只有将匹配上请求方法的路径才能交给对应的视图处理函数取处理。所有的路由,默认只接受 get 请求
		@app.route('/xxx/xxx',methods=['POST'])
		def xxx:
			# 该函数只能接受post请求
			pass

		@app.route('/xxx/xxx',methods=['GET','POST'])
		def xxx:
			# 该函数既能接受get请求也能接受post请求
			pass
	5.URL的反向解析
		正向解析:程序自动解析,根据@app.route()中的访问路径,来匹配处理函数

		反向解析:通过视图处理函数的名称自动生成对应的访问路径

		在Flask中要实现反向解析的话需要使用 :
			url_for(funName,args) 
				funName:要生成地址的函数名
				args:该地址中需要的参数

6.模板 - Templates

1.搭建结构
from flask import Flask
app = Flask(name)

@app.route('/')
def fun():
	return ""

if __name__ == "__main__":
	app.run(debug=True,port=6000)

2.路由
@app.route() 表示路由

@app.route('/') : 表示根路径 / 首页
@app.route('/index') : 表示 http://localhost:5000/index

1.带参数路由
	@app.route('/index/<name>')
	def index(name):
		return ""

	@app.route('/index/<name>/<gender>')
	def index(name,gender):
		return ""

	@app.route('/index/<int:age>')
	def index(age):
		return ""
	
	类型转换器:
		默认 :字符串,不能包含 /
		int: :整型
		float: :浮点型
		path: :字符串,允许包含 /

2.多个访问路径交给同一视图处理函数
	http://localhost:5000/index
	http://localhost:5000/index/wangwc
	
	@app.route('/index')
	@app.route('/index/<name>')
	def index(name=None):
		if name is None :
			xxxx xxxx
		return ""

3.路由的反向解析
函数 :
s = url_for(funName,arg1=value1,arg2=value2)

M : Models 模型层
T : Templates 模板层
V : Views 视图层

1.模板 - Templates
1.什么是模板
模板 , 在Flask 中就是允许响应给用户看的网页
在模板中,允许包含"占位变量"来表示动态的内容
模板最终也会被解析成字符串再响应给客户端,这一过程通常称为"渲染"

	Flask中的模板是依赖于 Jinja2 的模板系统
2.模板的设置
	默认情况下,Flask会在程序文件夹中的 templates 的子文件夹中搜索模板

	默认情况下,需要手动创建 templates 文件夹
	
3.模板的渲染
	作用:在视图中,将模板文件(xx.html)渲染成字符串之后,再响应给客户端浏览器
	函数:render_template('xxx.html')
		return render_template('xxx.html')
4.模板中的语法(重难点)
	1.变量
		变量是一种特殊的占位符,告诉模板引擎该位置的值是从渲染模板时的数据中获取出来的。

		在视图中 :
			@app.route('/')
			def index():
				return render_template('xxx.html',变量1=值1,变量2=值2,..)

				return render_template('xxx.html',name='laowang',age=35)
		在模板中 :
			{{变量名}}
			
			<h1>{{name}}</h1>
		练习:
			在 01-template.html基础上,完成下列效果显示:
			歌名 :《绿光》
			作词 : 宝强
			作曲 : 乃亮
			演唱 : 羽凡
	2.过滤器
		1.什么是过滤器
			过滤器是允许在变量输出前改变变量的值
		2.语法
			{{变量|过滤器}}
			
			Jinja2 模板中常见过滤器:
			过滤器名           说明
			capitalize         首字符变大写,其他变小写
			lower              将值转换为小写
			upper              将值转换为大写
			title              将值中的每个单词首字符变大写
			trim               去掉值两边的空格
	3.标签
		1.什么是标签
			每个标签标示的是不同的服务器端的功能
		2.常用标签
			1. if 标签
				1.基本if结构
					{% if 条件 %}
					{% endif %}

				2.if ... else ... 结构
					{% if 条件 %}
						满足条件时要运行的代码
					{% else %}
						不满足条件时要运行的代码
					{% endif %}
				3.if ... elif ... elif ... else
					{% if 条件1 %}
						满足条件1,要运行的代码
					{% elif 条件2 %}
						满足条件2,要运行的代码
					{% elif 条件3 %}
						满足条件3,要运行的代码
					{% else %}
						以上条件都不满足的时候,要运行的代码
					{% endif %}
			2. for 标签
				{% for 变量 in 元组|列表|字典 %}
				{% endfor %}

				在 Jinja2 模板的循环中,支持内部变量 - loop
				loop作用:记载当前循环中的一些相关信息
				loop 常用属性:
					1. index
						用法:loop.index
						作用:记录当前循环的次数,从 1 开始记录
					2. index0
						用法:loop.index0
						作用:同上,从0开始记录
					3. first
						用法:loop.first
						作用:值为True,则表示当前循环是第一次循环
					4. last
						用法:loop.last
						作用:值为True,则表示当前循环是最后一次循环
			3. macro 标签 (宏)
				1.作用
					相当于是在模板中声明函数
				2.语法
					使用 {% macro %} 声明宏

					{% macro 名称(参数列表) %}
						xxxx  xxxx
					{% endmacro %}
				3.在独立的文件中声明宏
					1.创建 macro.html 模板文件
						作用:定义项目中要用到的所有的宏
					2.在使用的网页中,导入 macro.html 
						{% import 'macro.html' as macros %}
			4. include 标签
				将其他的模板文件包含到当前的模板文件中
				语法:{% include 'xxx.html' %}
5.静态文件处理
	1.什么是静态文件
		在Flask中不能与服务器动态交互的文件都是静态文件
		如:图片,css文件,js文件,音视频文件,...
			<img src="images/a.jpg">
			<link rel="" href="css/a.css">
			<script src="js/a.js"></script>
			<video src="mp4/a.mp4"></video>
			<audio src="music/a.mp3"></audio>
	2.静态文件的处理
		1.所有的静态文件必须放在名为 static 的目录中
			static目录要放在项目的根目录处
			FlaskDemo02
				run01.py
				templates
					01-xxx.html
					02-xxx.html
				static
					images
						a.jpg
						b.jpg
					js
						body.js
						slider.js
					css
		2.所有的静态文件必须通过 /static/ 路径访问
			/static/images/a.jpg

			/static 要到静态资源目录中继续搜索

作业:
搭建 Blog 项目结构
1.创建项目 - Blog
2.将 所有的 html 文件 copy 到 templates 目录中作为模板
3.创建 static 目录,将 js 目录,css目录,images目录 copy到 static 中
4.创建 路由 /
访问 根路径时,显示首页模板(index.html)
要求:css,images,js 都能正常显示

params = {
'author': '奥斯特罗夫斯基',
'dic': {'WWC': '隔壁老王', 'LZ': '吕泽', 'WMZ': '老魏', 'MM': '蒙蒙'},
'bookName': '钢铁是怎样炼成的',
'tup': ('水浒传', '三国演义', '红楼梦', '西游记'),
'price': 32.5,
'list': ['漩涡鸣人', '卡卡西', '自来也', '佐助'],
'person': <main.Person object at 0x7f157c2c9048>
}

params['author']

1.模板
1.模板设置
所有的模板默认要放在项目中的 templates 目录中
2.渲染模板
html = render_template('xxx.html',args)
3.模板中的语法
1.变量
由后端的视图传递给模板中的一些动态数据
模板:{{变量}}
2.过滤器
在变量输出之前对变量进行一个修改
语法:{{变量|过滤器}}
ex:
{{var|upper}}
{{var|title}}
{{var|capitalize}}
... ...
3.标签
1. if 结构
1. {% if 条件 %} ... {% endif %}
2.
{% if 条件 %}
...
{% else %}
...
{% endif %}
3.
{% if 条件1 %}
...
{% elif 条件2 %}
...
{% else %}
...
{% endif %}
2. for 结构
{% for 变量 in 列表|字典|元组 %}

			内置变量 :loop
				loop.index : 当前循环遍历的次数,以 1 作为起始值
				loop.index0: 同上,以 0 作为起始值
				loop.first : True的话则表示是第一次循环
				loop.last : True的话则表示是最后一次循环
	4.宏
		{% macro 名称(参数) %}
			...
		{% endmacro %}

		{{名称(参数)}}

		在 macro.html 中声明所有的宏
		macro.html
			{% macro 名称1(参数) %}
				...
			{% endmacro %}

			{% macro 名称1(参数) %}
				...
			{% endmacro %}
		在使用的网页中,引入 macro.html
			{% import 'macro.html' as macros %}
			{{macros.名称(参数)}}
	5包含
		{% include 'xxx.html' %}

2.静态文件
1.所有的静态文件必须保存在 static 目录中
static 目录 存放在 项目根目录下的
2.所有的静态文件的访问必须通过 /static
/static 告诉服务器取 static 目录中继续搜索剩余内容

=========================================================
1.模板
1.静态文件地址的反向解析
url_for('static',filename='<file_path>')
ex:
url_for('static',filename='images/b041.jpg')
结果: /static/images/b041.jpg
2.模板的继承
1·什么是模板的继承
模板的继承类似于类的继承,如果一个模板中出现的内容来自于另一个模板的话,那么就可以使用继承的方式来简化开发
2.语法
1.父模板
需要定义出哪些东西在子模板中是可以被重写的
{% block 块名 %}
父模板中正常显示的内容
{% endblock %}
block:
1.在父模板中是可以正常显示的,没有任何影响
2.在字模板中是可以被重写的
2.子模板
1.需要指定继承自哪个父模板
{% extends '父模板名称' %}
2.重写父模板中对应的内容
{% block 块名 %}
此处编写的内容会覆盖掉父模板中同名block的内容

					允许通过 {{super()}} 来调用父模板中的内容
				{% endblock %}

2.修改配置
1.构建Flask 应用时允许指定的配置信息
app=Flask(
name,
template_folder='muban',
static_url_path='/s',
static_folder='/sta')

		template_folder : 指定存放模板的文件夹名称
		static_url_path : 访问静态资源的路径
			http://localhost:5000/s/xxx 查找静态资源文件
		static_folder : 指定存放静态文件的目录名称
			在项目的根目录中 ,有一个名为 sta 的目录用于存放静态文件
2.启动程序的运行配置
	app.run(
		debug = True,
		port = 5555,
		host = '0.0.0.0'
	)

	host : 指定访问地址,0.0.0.0 表示局域网内的任何机器都可以访问网站

3.请求(request) 和 响应(response)
1.HTTP协议
Request Headers - 请求消息头
Response Headers - 响应消息头
2.请求对象 - request
request - 请求对象,封装了所有与请求相关的信息。如:请求数据,请求消息头,请求路径,... ...
在Flask中,要使用 request 的话,必须先导入
from flask import request

	1.request的常用成员
		1.scheme : 获取请求方案(协议)
		2.method : 获取本期请求的请求方式(重点)
		3.args : 获取使用get请求方式提交的数据
		4.form : 获取使用post请求方式提交的数据
		5.cookies : 获取 cookies 的相关信息
		6.headers : 获取 请求消息头 的相关信息
		7.files : 获取上传的文件
		8.path : 获取请求的url地址(进入到主机后的请求资源地址,不包含请求参数)
		9.full_path : 获取请求的url地址(进入到主机后的请求资源地址,包含请求参数)
		10.url : 获取完整的请求地址,从协议开始的地址
	2.获取请求提交的数据
		1.get 请求方式
			1.表单允许实现get请求
				<form action="" method="get">
					姓名:<input name="uname">
				</form>
			2.在请求地址后拼请求提交的参数
				http://localhost:5000/06-get?uname=xxx&upwd=xxx

			获取 get 请求方式提交的数据 :
			request.args 封装的是get请求的数据
		2.post 请求方式
			post请求只有在表单中才能够被触发
			<form method="post">

			获取 post 请求提交的数据 :
				request.form 封装的就是 post 请求的数据,类型为字典

				request.form['name'] : 获取 name 对应的值
				request.form.get('name') : 获取 name 对应的值
				request.form.getlist('name') : 获取 name 列表数据(如复选框,下拉列表)
				练习:
					1.访问地址为 http://localhost:5000/07-form-post 能够去往07-form.html模板
					2.在 07-form.html 中
						包含一个表单,post 提交方式,提交地址为 /07-post,控件如下
						1.文本框 - 用户名
						2.密码框 - 用户密码
						3.文本框 - 用户邮箱
						4.文本框 - 真实姓名
						5.提交按钮
					3.在 07-post 中
						获取所有请求提价的数据并打印在终端中

['class', 'delattr', 'dict', 'dir', 'doc', 'enter', 'eq', 'exit', 'format', 'ge', 'getattribute', 'gt', 'hash', 'init', 'le', 'lt', 'module', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref', '_cached_json', '_get_data_for_json', '_get_file_stream', '_get_stream_for_parsing', '_load_form_data', '_parse_content_type', 'accept_charsets', 'accept_encodings', 'accept_languages', 'accept_mimetypes', 'access_route', 'application', 'args', 'authorization', 'base_url', 'blueprint', 'cache_control', 'charset', 'close', 'content_encoding', 'content_length', 'content_md5', 'content_type', 'cookies', 'data', 'date', 'dict_storage_class', 'disable_data_descriptor', 'encoding_errors', 'endpoint', 'environ', 'files', 'form', 'form_data_parser_class', 'from_values', 'full_path', 'get_data', 'get_json', 'headers', 'host', 'host_url', 'if_match', 'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since', 'input_stream', 'is_json', 'is_multiprocess', 'is_multithread', 'is_run_once', 'is_secure', 'is_xhr', 'json', 'list_storage_class', 'make_form_data_parser', 'max_content_length', 'max_form_memory_size', 'max_forwards', 'method', 'mimetype', 'mimetype_params', 'on_json_loading_failed', 'parameter_storage_class', 'path', 'pragma', 'query_string', 'range', 'referrer', 'remote_addr', 'remote_user', 'routing_exception', 'scheme', 'script_root', 'shallow', 'stream', 'trusted_hosts', 'url', 'url_charset', 'url_root', 'url_rule', 'user_agent', 'values', 'view_args', 'want_form_data_parsed']

Accept-Encoding: gzip, deflate
Cookie: csrftoken=n5KInc6ybogDshzgCIGsNgKuPLCIWv1Aus1twEtssK1TkZglnD51NlBa4axghzg1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0
Host: localhost:5000

Connection: keep-alive
Cookie: csrftoken=n5KInc6ybogDshzgCIGsNgKuPLCIWv1Aus1twEtssK1TkZglnD51NlBa4axghzg1
Host: localhost:5000
Upgrade-Insecure-Requests: 1
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Referer: http://localhost:5000/02-parent
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8

http://localhost:5000/06-get?uname=wangwc&upwd=lvze
http://localhost:5000/06-get?uname=laowei&upwd=wangwc

1.模板继承
1.父模板
{% block 块名 %}
{% endblock %}
2.子模板
1.{% extends '父模板名称' %}
2.{% block 块名 %} ... {% endblock %}
2.修改配置
1.创建应用的配置
app=Flask(
name,
template_folder="xxx",
static_url_path="/s",
static_folder="xxx")
2.启动应用时的配置
app.run(
debug=True,
port="5678",
host="0.0.0.0"
)
3.请求
1.请求对象 - request
1.request
from flask import request

		@app.route('/xxx')
		def xxx():
			request : 可以表示请求的相关信息
	2.request的常用成员
		1.request.scheme
		2.request.method
		3.request.args
		4.request.form
		5.request.cookies
		6.request.url(完整路径)
		7.request.path(不带参数)
		8.request.full_path(带参数)
		9.request.headers
			request.headers.get('Referer','')
			request.headers.get('消息头','')
	3.获取请求提交的数据
		1.GET 请求
			1.表单 method=get
			2.所有地址栏的请求都是get

			特点:http://localhost:5000/login?uname=xx&uage=5

			取值:
				request.args['uname']
				request.args.get('uage')
		2.POST 请求
			1. 表单 method='post'

			取值:
				request.form['']
				request.form.get('')


		想看登录页面: /login
		在/login中,想提交数据给服务器:/login

		在 /login 中,要判断用户的请求方法
			如果是 get 的话,则去往 登录页面
			如果是 post的话,则处理用户提交的数据

======================================================
1.响应(response)
1.什么是响应
响应就是由服务器端带给客户端的内容,对应着请求。
响应可以是普通的字符串,模板 或 重定向
return "普通字符串"
return render_template('xxx.html')
2.响应对象
响应对象:将响应的内容封装到一个对象中,可以完成更多的响应的行为(如:增加cookies,...)

	在Flask中,使用 make_response() 构建响应对象
	from flask import make_response
	@app.route('/xxx')
	def xxx():
		resp = make_response('响应内容')
		# 允许实现其他的响应行为
		
		return resp

3.重定向
	1.什么是重定向
		由服务器端通知客户端重新向一个新的地址发送请求
	2.语法
		from flask import redirect

		return redirect('重定向地址')

		===============================

		resp = redirect('重定向地址')
		#借助resp实现其他的响应行为
		return resp

2.文件上传
1.注意问题
表单中如果有文件上传的话,必须遵循以下两个要求
1.提交方式 method 必须为 post
2.表单的 enctype 属性的值 必须为 multipart/form-data
2.服务器端
1.通过 request.files 获取上传文件
f = request.files['文件框的name值']
2.通过 f.save(保存路径) 将文件保存至指定目录处
通过 f.filename 获取文件的名称
f.save('static/'+f.filename)
3.模型 - Models
1.什么是模型
模型,是根据数据库中表的结构而创建出来的class。
每一张表对应到编程语言中,就是一个class
表中的每一个列对应到编程语言中就class中的一个属性
2.模型的框架 - ORM
1.什么是ORM
ORM :Object Relational Mapping
简称: ORM,O/RM ,O/R Mapping
中文名:对象关系映射
2.ORM的三大特征
1.数据表(table)到编程类(class)的映射
数据库中的每一张表 对应到 编程语言中 都有一个类
在ORM中:
允许将数据表 自动 生成一个类
允许将类 自动 生成一张数据表
2.数据类型的映射
将数据库表中的字段以及数据类型 对应到 编程语言中类的属性
在ORM中
允许将表中的字段和数据类型自动映射到编程语言中
也允许将类中的属性和数据类型也自动映射到表中
3.关系映射
将数据库中表与表之间的关系 对应 到编程语言中类与类之间的关系
数据库中表与表之间的关系:
1.一对一
外键,主键,唯一约束
A表中的一条数据只能与B表中的一条数据相关联
2.一对多
外键,主键
A表中的一条数据可以与B表中的任意多条数据相关联,反之,B表中的一条数据只能与A表中一条数据相关联
ex:老师(Teacher)与课程(Course)
一门课程可以被多个老师所教授
一个老师最多只能教一门课程
3.多对多
通过第三张关联表去关联两张表
A表中的一条数据可以与B表中的任意多条数据相关联,B表中的一条数据也可以与A表中的任意多条数据相关联
3.ORM优点
1.封装了数据库中所有的操作,大大提高了开发效率
2.可以省略庞大的数据访问层,即便不用SQL编码也能完成对数据的CRUD的操作
3.Flask 中的 ORM框架
1.数据库 和 框架配置
在Python 和 Flask 中,使用的ORM框架是 - SQLAlchemy
在Flask 中想使用 SQLAlchemy的话,需要进行安装:
pip3 install sqlalchemy
pip3 install flask-sqlalchemy
2.创建数据库

Student (id,stu_name)
Course (id,course_name)
Student_Course (id,student_id,course_id)

select s.stu_name,c.course_name from Student as s
inner join Student_Course as sc
on s.id = sc.student_id
inner join Course as c
on sc.course_id = c.id
where s.stu_name='马晕'

消息头:
Content-Type
Referer

@app.route('/show/')
def show(name):
name : 参数

http://localhost:5000/show/wangwc

1.响应对象
1.响应对象
resp = make_response("")
return resp
2.重定向
由服务器通知浏览器向新的地址发送一个请求
resp = redirect('/xxx')
return resp
2.文件上传
1.注意问题
表单的method必须为 post
表单的enctype必须为 multipart/form-data
2.服务器端
1.request.files 获取上传的文件
f = request.files['xx']
2.将文件保存至服务器的指定目录处
f.save('保存路径')

		1.获取项目的绝对路径
			basedir = os.path.dirname(__file__)
		2.通过时间字符串代替文件名称
			1.获取当前的时间字符串
				ftime = datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")
			2.获取文件扩展名
				ext = f.filename.split('.')[1]
			3.拼完整的上传路径
				upload_path=os.path.join(basedir,'static/upload',ftime+'.'+ext)

3.ORM
1.ORM
1· 中文名:对象关系映射
2. ORM三大特征
1.数据表 到 编程类的映射
2.数据类型的映射
3.关系映射
2.Python 和 Flask 中 使用 ORM
Python 和 Flask :SQLAlchemy
Flask :必须要有 Flask-SQLAlchemy 的支持
3.Flask中配置数据库
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

	app = Flask(__name__)

	app.config['SQLALCHEMY_DATABASE_URI']="mysql://root:123456@localhost:3306/flask"
	db = SQLAlchmey(app)

===============================================

1.模型 - Models
1.定义模型
模型:数据库中的表在编程语言中的体现,其本质就是一个python类(模型类 或 实体类)

	语法:
		class MODELNAME(db.Model):
			__tablename__="TABLENAME"
			COLUMN_NAME=db.Column(db.TYPE,OPTIONS)

		1.MODELNAME : 定义模型类的名称,根据表名设定
		2.TABLENAME : 映射到数据库中表的名称
		3.COLUMN_NAME : 属性名,映射到数据表就是列名
		4.TYPE : 映射到列的数据类型
		5.OPTIONS : 列选项

	db.TYPE 列类型如下:
		类型名       python类型      说明
		Integer      int              普通整数,32位
		SmallInteger int              小范围整数,通常16位
		BigInteger   int或long				不限精度整数
		Float        float            浮点数
		Numeric      decimal.Decimal  定点数
		String       str              变长字符串
		Text         str              变长字符串,优化
		Unicode      unicode          变长Unicode字符串
		UnicodeText  unicode          优化后的变长Unicode串
		Boolean      bool             布尔值
		Date         datetime.date    日期
		Time         datetime.time    时间
		DateTime     datetime.datetime日期和时间
	OPTIONS 列选项:
		选项名          说明
		primary_key     如果设置为True表示该列为主键
		unique          如果设置为True表示该列值唯一
		index           如果设置为True表示该列要创建索引
		nullable        如果设置为True表示该列允许为空
		default         表示该列的默认值

	练习:
		1.创建 Student 模型类
			表名:student
			字段:
				1.id ,主键,自增
				2.sname , 姓名,长度为30并且不允许为空的字符串
				3.sage,年龄,整数
		2.创建 Teacher 模型类
			表名:teacher
			字段:
				1.id , 主键,自增
				2.tname ,姓名,长度为30并且不允许为空的字符串
				3.tage,年龄,整数
		3.创建Course 模型类
			表名:course
			字段:
				1·id,主键,自增
				2·cname ,课程名称长度为30并且不允许为空的字符串
2.数据库操作 - 插入
	1.创建实体对象
	2.完成插入
		db.session.add(实体对象)
		db.session.commit() 
3.数据库操作 - 查询
	1.基于 db.session 进行查询
		1.db.session.query()
			该函数会返回一个Query对象,类型为BaseQuery
			该对象中包含了实体类对应的表中的所有的数据

			该函数可以接收一个或多个参数,参数们表示的是要查询的实体对象是谁
		2.查询执行函数
			目的:在query()的基础上得到最终想要的结果
			语法:db.session.query(...).查询执行函数()
			函数              说明
			all()             以列表的方式返回query()中所有查询函结果
			first()           返回查询结果中的第一个结果,如果没有结果,则返回None
			first_or_404()    返回查询结果中的第一个结果,如果没有结果的话,则终止并返回404
			count()           返回查询结果的数量
		3.查询过滤器函数
			作用:在查询的基础上,筛选部分行数据
			语法:db.session.query(...).过滤器函数().查询执行函数()
			过滤器函数       说明
			filter()         按指定条件进行过滤(多表,单表,定值,不定值)       
			filter_by()      按等值条件过滤时使用
			limit()          按限制行数获取
			order_by()       根据指定条件进行排序
			group_by()       根据指定条件进行分组

			过滤器函数详解:
			1.filter()
				注意:条件必须由 模型类.属性 构成
				1.查询年龄大于30的Users的信息
					db.session.query(Users).filter(Users.age>30).all()
				2.查询年龄大于30并且id大于1的Users的信息
					db.session.query(Users).filter(Users.age>30,Users.id>1).all()
				3.查询年龄大于30或者id大于1的Users的信息
					注意:查询 或 的操作,要借助于 or_()
					db.session.query(Users).filter(or_(Users.age>30,Users.id>1)).all()
				4.查询id为2的Users的信息
					注意:等值判断必须用 ==
					db.session.query(Users).filter(Users.id==2).all()
				5.查询 email 中包含 'w' 的Users的信息 - 模糊查询
					注意:模糊查询like需要使用实体类中属性提供的like()
					db.session.query(Users).filter(Users.email.like('%w%')).all()
				6.查询 id 在 [2,3] 之间的 Users 的信息
					注意:模糊查询in需要使用实体类中属性提供的in_([])
			2.聚合函数
				db.session.query(func.聚合函数(列名).label('别名')).all()
			3.filter_by()
				查询 id=5的Users的信息
				db.session.query(Users).filter_by(id=5).all()
			4.limit()
				result = db.session.query(Users).limit(2).all()
				result = db.session.query(Users).limit(2).offset(1).all()
			5.order_by()
				# 按照id列的值降序排序
				db.session.query(Users).order_by("id desc")
				# 按照age列的值降序排序,二级排序按照id升序排序
				db.session.query(Users).order_by("age desc,id asc").all()
			6.group_by()
				db.session.query(Users).group_by('age').all()
	2.基于 Models   类进行查询 

数据库中的一行:实体
实体完整性:表中的实体不能完全重复 - 主键

SELECT users.id AS users_id, users.username AS users_username, users.age AS users_age, users.email AS users_email
FROM users

SELECT users.id AS users_id, users.username AS users_username, users.age AS users_age, users.email AS users_email, course.id AS course_id, course.cname AS course_cname
FROM users, course

查询Users中所有人的年龄的总和
select sum(age) as 'sum_age' from users

select id,sum(age) as 'sum_age' from users

db.session.query(Users.id,func.sum('age'))

select * from users limit 1,2

1.创建模型
class MODLENAME(db.Model):
tablename=TABLENAME
COLUMN_NAME=db.Column(db.TYPE,OPTIONS)

MODELNAME : 模型名称
TABLENAME : 对应的表名
COLUMN_NAME : 对应的列名
TYPE : 列类型
OPTIONS : 列选项

TYPE:	
	Integer,SmallInteger,BigInteger,Boolean
	Float,Numeric
	String,Text,Unicode,UnicodeText
	Date,Time,DateTime
OPTIONS:
	primary_key : True or False
	unique : True or False
	index : True or False
	nullable : True or False
		默认是允许为空(True)
	default : 定义默认值

2.数据库操作
1.插入
db.session.add(Models对象)
db.session.commit()

	自动提交:
		app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
2.查询
	1.基于 db.session 查询
		1.db.session.query()
			查询基础,返回查询对象
		2.查询执行函数
			目的:用于得到最终的结果
			all() , first() , first_or_404() , count()
		3.查询过滤器函数
			目的:在基础查询后增加筛选条件
			1.filter()
				注意:必须使用 实体类.属性 做筛选
				1.db.session.query(Models).filter(Models.column > num).all()
				2.db.session.query(Models).filter(Models.col1>num1,Models.col2>num2)
				3.db.session.query(Models).filter(or_(条件1,条件2)).all()
				4.db.session.query(Models).filter(Models.column.like('%w%')).all()
				5.db.session.query(Models).filter(Models.column.in_(['','',''])).all()
				6.聚合
					db.session.query(func.聚合函数(Models.Column).label('别名'))
						聚合函数:
							sum() : 求和
							count() : 求数量
							max()
							min()
							avg()
			2.filter_by()
			3.limit()
			4.order_by()
			5.group_by()
	2.基于 Models

=================================================
1.数据库的操作
1.增加(略)
2.查询
1.基于db.session(略)
2.基于Models进行查询
Models.query.查询过滤器函数(条件参数).查询执行函数()
3.删除
1.查询出要删除的实体对象
u=db.session.query(Models).filter_by(xxx).first()
2.根据提供的 删除方法进行删除
db.session.delete(u)
注意:
真正的删除并不是通过删除操作完成,而是通过修改完成的
4.修改
1.查
将 要修改的信息查询出来
2.改
实体对象.属性 = 值
3.保存
db.session.add(实体对象)
2.关系映射
1.一对多
语法:
1.在 "多" 的实体中
增加一个列,引用自"一"表的主键列
外键列名 = db.Column(db.Integer,db.ForeignKey('主表.主键'))
2.在 "一" 的实体中
增加关联属性以及反向引用关系

			ex:
				关联属性:
					在 course 对象中,通过一个属性能够得到对应的所有的teacher们
					关联属性,是应该加在 Course 的实体类中
				反向引用:
					在 teacher 对象中,通过一个属性能够得到对应的course
					反向引用关系属性,是应该加在 Teacher 的实体类中
			增加关联属性和反向引用关系:
			属性名=db.relationship('多表实体类名',关系选项)
			关系选项:
			选项名               说明
			backref              在关系的另一个模型中添加的反向引用属性名
				(准备在"多"的实体中增加对"一"的实体引用的属性名)
			lazy                 指定如何加载当前的相关记录
			                     select:首次访问时加载记录
													 immediate:源对象加载后马上加载相关记录
													 subquery:效果同上,利用子查询方式加载记录
													 noload:永不加载记录
													 dynamic:默认不加载记录,但会提供加载记录的查询
			uselist              如果设置为False,表示不使用列表表示关联数据,而使用标量
			secondary            指定多对多关系映射中的关联表的名字
2.一对一
	1.什么是一对一
		A表中的一条记录只能与B表中的一条记录相关联
		B表中的一条记录只能与A表中的一条记录相关联
	2.在SQLAlchemy中的体现
		1.在任意一个类中增加
			外键列名 = db.Column(db.Integer,db.ForeignKey('主键表.主键列'))
		2.在另外一个类中增加
			关联属性 和 反向引用关系属性
			属性=db.relationship('关联的实体类',backref='反向引用属性名',uselist=False)









<a href="javascript:xxxx()">xxx</a>

1.数据库的操作
1.查询 - 基于 Models 查询
Models.query.查询过滤器().查询执行函数()
2.修改
1.查
得到数据
2.改
通过实体对象修改数据
3.保存
db.session.add(实体)
3.删除
db.session.delete(实体)
2.关系映射
1.一对多
1.在 "多" 实体中
外键列名=db.Column(db.Integer,db.ForeignKey('主表.主键'))
2.在 "一" 实体中
属性名=db.relationiship("多的实体类名",backref="属性名",lazy="dynamic")

		lazy:指定如何加在相关记录
			1.select
				首次访问时加载
			2.immediate
				源对象加载后立马加载相关数据
			3.subquery
				效果同上,使用的是子查询
			4.noload
				永不加载
			5.dynamic
				不加载记录,但提供加载记录的查询
		uselist:
			如果设置为False,表示不使用列表而使用的是标量
		secondary:
			指定多对多关系中关联表的名字
2.一对一
	1.在 "多" 实体类中体现
		外键列名=db.Column(db.Integer,db.ForeignKey('主表.主键'))
	2.在 "一" 实体类中体现
		属性名 = db.relationship("关联的实体类",backref="",uselist=False)

=========================================================
1.关系映射
1.多对多
1.什么是多对多
A表中的一条数据可以与B表中任意多条数据相关联
B表中的一条数据可以与A表中任意多条数据相关联
2.实现
在数据库中使用第三张表(关联表)
在编程语言中,可以不编写对应的实体类
1.创建第三张表
student_course = db.Table(
'student_course',#在数据库中表名
db.Column('id',db.Integer,primary_key=True),
db.Column(
'student_id',
db.Integer,
db.ForeignKey('student.id')),
db.Column(
'course_id',
db.Integer,
db.ForeignKey('course.id'))
)
2.cookies / cookie
1.什么是cookies
cookie 是一种数据存储手段
将一段文本保存在客户端(浏览器)的一种手段,并可以长时间保存
2.cookies的使用场合
1.记住密码
2.记住搜索关键词
3.Flask 中使用 cookies
1.使用响应对象,将数据保存进cookies(客户端)
1.resp = make_response("字符串"|render_template())
2.resp = redirect('地址')

		cookies 的语法
		响应对象.set_cookie(key,value,max_age)
			key:保存的cookie的名称
			value:保存的cookie的值
			max_age:保存的时间,取值为数字,默认以 s 为单位
				60 :一分钟
				60 * 60 :一小时
				60 * 60 * 24 :一天
				60 * 60 *24 * 365 :一年
	2.获取 cookie 的值
		每次向服务器发送请求时,都会把cookie中的数据封装到request中并带到服务器上
		在flask中通过 request.cookies 获取所有的cookies值
	3.删除cookie的值
		响应对象.delete_cookie('key')









{
	'uname': 'jack', 
	'csrftoken': 'n5KInc6ybogDshzgCIGsNgKuPLCIWv1Aus1twEtssK1TkZglnD51NlBa4axghzg1'
}

3.session - 会话
1.什么是session
session是保存在服务器上,为每个浏览器所开辟的一段空间
2.session 在 Flask 中的实现
1.配置 SECRET_KEY
app.config['SECRET_KEY']="xiangxieshaxiesha"
2.使用session
from flask import session

		1.向session中保存数据
			session['key']=value
		2.从session中取值
			value = session['key']
			value = session.get('key','')
		3.从session中删除数据
			del session['key']
posted @ 2018-11-29 20:41  IndustriousHe  阅读(542)  评论(0编辑  收藏  举报