Flask 轻量级框架 WEB 框架
AJAX 在web中完成异步请求和响应
Django 重量级WEB框架javascript
Python Webcss
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,控制器,用于与用户交互的部份内容(请求和响应)html
M --- M T --- V V --- C
4.Flask框架
1.什么是Flask框架
Flask是一个基于Python而且依赖于Jinja2模板引擎和Werkzeug WSGI服务的一个微型框架
WSGI :Web Server Gateway Interface(WEB服务网关接口)java
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"python
# 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.模板 - Templatesmysql
1.搭建结构
from flask import Flask
app = Flask(name)web
@app.route('/') def fun(): return "" if __name__ == "__main__": app.run(debug=True,port=6000)
2.路由
@app.route() 表示路由sql
@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 列表|字典|元组 %}
{% endfor %}
内置变量 :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='
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']