1.flask(先后端交互的接口)(返回api(json))html
2.MongoDB NoSQL(自由度高,(没什么限制),操做就难)4版本(多了个事务)+3.4前端
3.人工智能 A.I. 应用技术 Not 算法和机器学习java
4.webSocket 全双工通信 IM即时通信python
5.Mui(布局,布局一个 ) + HTML5Plus(打开硬件有封装) App (工做了,就是一个小儿科,这些框架,质的飞跃)程序员
6.智能玩具 + 机器学习web
Django 15天面试
优点:组件全 - admin - Model ORM - Forms
教科书式(其余框架和他像)算法
劣势:加载的组件是所有的组件 - 占用资源较高
重型框架django
Flask 3 天json
优点:轻如鸿毛 扩展性极强 三方组件全
劣势:什么组件都没有
三方组件全 - 版本兼容问题 致使不稳定
线程的支持(不如dj)
安装
新建pure python项目
-new environment 选择 Virtualenv
--选择interpreter
---选择make available to all projects
启动
在大目录下,新建一个py文件
from flask import Flask #导入Flask以及别的 app=Flask(__name__) #Flask第1个参数 模块名 app.run() #默认访问http://127.0.0.1:5000/ 端口启动也能够指定别的端口 好比:# app.run('0.0.0.0',9527)
Flask 源码:
def __init__( self, import_name,
返回错误 503 能够链接,可是没有返回视图
from flask import Flask,render_template #返回模板 app=Flask(__name__) @app.route('/') # route() 装饰器 url 触发--> 函数 def home(): # return 1 #不能返回整型 return 'hello world' #可字符,字典,列表 @app.route('/index') def index(): return render_template('index.html') #来渲染模板。 app.run()
方法:
1 写一个templates
把index.html 放了里面 而后飘黄
2 make dir template dir 选择jinja2 (webpy ,django,等) (Django封装了(要不也可使用jiaja2了) jinja2最好 )
Flask 会在 templates 文件夹里寻找模板, 以后就能够向django同样使用模板了,自动补全
因此,若是你的应用是个模块,这个文件夹应该与模块同级;若是它是一个包,那么这个文件夹做为包的子目录:
状况 1: 模块:
/application.py /templates /hello.html
状况 2: 包:
/application /__init__.py /templates /hello.html
jsonify 模块
from flask import Flask,render_template,jsonify @app.route('/json') def my_jsonify(): # return jsonify({'a':1}) #字典转成json字符串 return {'k':1} #1.1后支持直接传字典
return jsonify(username=g.user.username,... --------》 This will send a JSON response like this to the browser:: { "username": "admin",...
flask 中的返回特殊封装 2个
1 jsonify 转换标准JSON格式
响应头中加入 Content-type:application/json
app/json 自动的将 转换成object?字典?
flask1.1下 直接返回字典了,能够不用使用jsonify (向下兼容了) (flask以前的的必须使用jsonify,做为一个开发两年的mn)
alt + 回车(补全import)
打开并返回文件内容,
自动识别文件类型,
响应头中加入了 Content-Type
前端 : 只和request有关系 全部response都是后端处理的 text image audio/mpeg(MP3) video/mp4(两次请求,http请求数据是有限制的,流媒体,节省服务器资源) my_file my_file 全部浏览器没法识别的东西: 都如下载的格式返回 好比zip格式的 Content-Type: application/x-zip-compressed 爬虫的时候: 采集视频难,一段一段,中间还得带验证码
当我传MP3MP4格式的时候,发现MP3格式的图标是? 而MP4的格式是文本同样(可是能够传说明没问题)
send_file代码以下:(文件都在主目录下)
@app.route('/my_file') def my_file(): # return send_file('1.png') # return send_file('app01.py') # return send_file('1.mp3') # return send_file('1.mp4') # return send_file('1.jpg') return send_file('1.zip')
做用:执行的时候才走,被别的调用的时候不走了
from flask import Flask,render_template app = Flask(__name__) @app.route('/login') def login(): return render_template('login.html') if __name__ == '__main__': # 只有调用的时候才执行 别的文件引入时候不执行 app.run()
<h1>login</h1> <form action="" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="pwd"> <input type="submit" value="登陆">
405 : 请求方式不被容许
127.0.0.1 - - [10/Jul/2019 10:32:53] "GET /login HTTP/1.1" 200 - 127.0.0.1 - - [10/Jul/2019 10:33:03] "POST /login HTTP/1.1" 405 -
解决:
@app.route('/login',methods=['POST','GET'])
route容许post和get方法
request是全局的(公共对象),第一个用户进来了,第二个用户也都能用 那就不支持多进程了,有解决方法
request.form 获取FormData的数据 - Form表单
request = LocalProxy(partial(_lookup_req_object, "request"))
if request.method == 'GET': #请求方式 return render_template('login.html') if request.method == 'POST': print(request.form) print(request.form.get('username')) print(request.form.to_dict()) return '200 OK'
ImmutableMultiDict([('username', 'asdfas'), ('pwd', 'adfasd')]) #多重字典 看到dict用get
request.headers #请求头中的数据 request.url #访问路径 http://127.0.0.1:5000/login request.path#路由地址 /login 综合获取 request.values #获取URL中的参数 也能够获取FormData中的数CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('ids', '2')]), ImmutableMultiDict([('username', '123'), ('pwd', '456')])]) request.values.get('id') # request.args.to_dict() #获取url参数{'id': '1', 'ids': '2'} request.args['id']) # key value key没有值会报错,get比较好 好比: KeyError: 'id' request.args.to_dict()['id'] request.environ #获取请求原始信息 #{'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', .........} request.base_url #获取url头,不包含参数 #http://127.0.0.1:5000/login request.json #请求头con-type:app/json 数据序列化 #None request.data #请求头中contype 不包含Form or data #b'' request.headers #Host: 127.0.0.1:5000
request.value的坑
因为都是ImmutableMultiDict([('id', '1'), 若是前端提交name写了id 那么.to_dict() 就会被覆盖 先写的dataform后写的url,url覆盖
默认保存到主目录(项目)下
my_file = request.files.get('my_file') my_file.save('save.jpg') fp = os.path.join('templates',my_file.filename) # my_file.save(fp) #指定目录保存到templates下
区分form和from的方法
Form 表单 - FormData f orm - 表单 from
django自带的
# app.config['DEBUG'] = True app.debug = True #避免重启 按ctrl + s 重启 切换也重启
<http://127.0.0.1:5000/login?id=1>
这样访问 ?传输参数 不会对地址路由形成影响 是传参了
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'} STUDENT_LIST = [ {'name': 'Old', 'age': 38, 'gender': '中'},... STUDENT_DICT = { 1: {'name': 'Old', 'age': 38, 'gender': '中'},.. def return render_template('index1.html', stu_info = STUDENT, stu_list = STUDENT_LIST, stu_dict = STUDENT_DICT,absum =ab)
<table border="1px"> <tr> <td>name</td> <td>age</td> <td>gender</td> </tr> <tr> <td>{{ stu_info.name }}</td> <td>{{ stu_info.get('age') }}</td> <td>{{ stu_info['gender'] }}</td> #三种方式均可以得到字典的 可是key的慎用
{% for foo in stu_list %} #(改性别) <td>{% if foo.gender!='男' and foo.gender!='女' %} 女 {% else %} {{ foo.gender }}
{% for id in stu_dict %} <tr> <td>{{ id }}</td> <td>{{ stu_dict[id].name }}</td> <td>{{ stu_dict.get(id).get('age') }}</td>
{% for id,s in stu_dict.items() %} <tr> <td>{{ id }}</td> <td>{{ s.name }}</td> <td>{{ s.get('age') }}</td>
id 和 s
{# {{ id }} {#1 {'name': 'Old', 'age': 38, 'gender': '中'} 2 {'name': 'Boy', 'age': 73, 'gender': '男'} 3 {'name': 'EDU', 'age': 84, 'gender': '女'}#} #} {# {{ s }}#}
@app.template_global() #全局的 def ab(a,b): return a+b
一般作一个模块,到引入就好了,都引入
return render_template('index1.html',absum =ab)#传到模板 #不用absum的 全局的
模板使用
center>{{ absum }}</center> <center>{{ ab(2,2) }}</center> #<function ab at 0x0000000003873488> #4
{% macro my_input(na,ty)%} <input type="{{ ty }}" name="{{ na }}"> {% endmacro %} {{ my_input('uname','text')}}
传给模板一个标签
my_in = Markup("<input type= 'text',name='uname'>") return render_template('index1.html',m=my_in)
{{m}} #使用
{{}} 引用 or 执行
{%%} 逻辑语法 if for else
今天上课都是由于一个,逗号困住,因此不得往下面的,惋惜,细节
登陆页面提交方式
<h1>login</h1> {#<form action="/login?id=1&ids=2" method="post" enctype="multipart/form-data">#} #url倒是post方式的提交 <form action="" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="pwd"> {# <input type="file" name="my_file">#} #提交文件 <input type="submit" value="登陆">
session和request同级的,不和Django同样,request.django
request = LocalProxy(partial(_lookup_req_object, "request")) session = LocalProxy(partial(_lookup_req_object, "session")) #基本同样
app.secret_key = '*Ud8fadjfadkjfaidjf' #验证码 @app.route('/login',methods=['POST',"GET"]) def login(): if request.method == 'GET': return render_template('login.html') uname = request.form.get('username') pwd = request.form.get('pwd') if uname == '123' and pwd == '123': session['username'] = uname
@app.route('/detail') def detail(): if session.get('username'): return render_template('index.html') else: return redirect('/login')
Flask中的Session 不是三方组件 //Flask-Session
from flask import session
session['username'] = uname #加入session
RuntimeError The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret. 解决: app.secret_key = '*Ud8fadjfadkjfaidjf' ####密钥的写法不是app.session,而是app
session 交由客户端保管
当客户端发起请求 -request 带上cookie - cookie中有session的加密字符串 -flask 收到session加密字符串 - 经过 secret_key 解密session的加密字符串 得到 {username : 123}
app.permanent_session_lifetime = 15 (默认是秒)
均可以改 这些内容 (别再源码里改,提出来改)进入源码: session-->global session app.py里的内容
"PERMANENT_SESSION_LIFETIME": timedelta(days=31),
程序里改:
app.permanent_session_lifetime = 15
查看在前端application-->Cookies--> 代替了cookie, network点击login里没有改
app.session_cookie_name = "I am Not Session"
app.testing = True
开启session - session['username'] = uname
建立一个字典 {username:123} 接下来 经过secret_key(密钥安全) + 时间戳 + 签名 加密 造成
eyJ1c2VybmFtZSI6IjEyMyJ9.XSVovw.g6ZxiiEw_0EhRHF--oTG9Ac-ZF8 session的加密字符串
签名.时间戳.数据
if uname == '123' and pwd == '123': session['username'] = uname
if uname == '123' and pwd == '123': session['username'] = uname session['username1'] = uname session['username2'] = uname
.eJyrViotTi3KS8xNVbJSMjQyVtKBCxhiiBhhiBhDRWoBGaYU8w.XSXASw.cExXNorpTmERznwqRl9mdO4Tu7Y 写了多个session,session就多了不少 由于{username:123,username1:123,} 有公共机制因此说: 不会太长了
if uname == '123' and pwd == '123': session['dasgas'] = '打分' session['ada'] = '网页'
.eJyrViotTi3KS8xNVbJSiik1NTK0iCk1SzFIUtKByxjiljLCLWWMLlULACpUIRM.XSXBYw.uZrsOt2eoTJX4pJPoxQk4wSxjJY(多了,由于2个汉字6个)
不能线上开debug,会暴露密钥,在前端页面显示错误的时候,可能就会暴露,相对安全不是绝对的安全了
错了好屡次了
a = 0 @app.route('/detail') def detail(): global a if session['username']: a += 1 print(a)
1 用装饰器装饰一个登陆函数
返回request(双重装饰器)
2 每个视图函数都加上装饰器
能写三遍的不写两遍,背诵默写,哪不会的
不要太依赖,若是没有pycharm怎么办
记事本怎么写,能不能写 (今天学的可不能够写)
以后多是各类工具
以后花钱买个 视频 看看破解版的 专业的(两三块钱) 不要更新 (把算法替换掉)
pycharm 是java写的, java的算法 , 乱码是算法的值,就连上了
技术:是掉接口的码农?仍是
架构:更偏向技术
懂技术的产品还能够
会,必需要全会,才算掌握一个语言 --龙
看面试官 眉心 就能够把人看紧张了
吹了27k,原本15k。。。压力也大
15 16 K的程序员 都是应用层次的 用过什么
25k的左右的是接触过什么架构 什么项目
吹得话: ai开放能力,找一个,学或者了解()
人工智能 有标签 ,提上简历,有一个算法,招标签
龙交的nlp,还真会点 18k,把本身吹太牛了,不敢去(很能吹的南方人 能吹offer多7个)
遇到特别不屑的,直接走,转身走(不要回头)
学习稍微难些
最新的框架,python最快的 (先天写的东西都比他快的不少)(世界上没有最好的语言,本身用的就是最好的,没有最好的程序员,本身) python数据计算很是快
STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'} ,
stu_info = STUDENT 时 , stu_info.name 等都没有值,是空的 ,而stu_info 有值 等于:
({'name': 'Old', 'age': 38, 'gender': '中'},)
之后不要犯这种错误
多加了个,成了元祖类型了(其实提示了tuple not get ,可是不看提示,看了也不懂把)
本身写程序出的错
1 AttributeError: read only property
request.method = ['POST','GET'] --->request.methods = ['POST','GET']
2 jinja2.exceptions.TemplateNotFound
jinja2.exceptions.TemplateNotFound: login.html #---> 扔到主目录下,把文件
3 Method Not Allowed (405 403)
The method is not allowed for the requested URL.
request.methods = ['POST','GET'] #这个写法不对,无法分配POST方法
-->@app.route('/login',methods=['POST',"GET"])#直接写上面
ctrl + enter 不是快速导入的命令
alt + enter 才是快速导入模块的命令
再加个命令 ctrl+shift+i 是前端的检查快捷键