flask1 + jinja2 day88

人工智能方向 - 智能玩具

-1 所学内容:

1.flask(前后端交互的接口)(返回api(json))

2.MongoDB NoSQL(自由度高,(没什么限制),操作就难)4版本(多了个事务)+3.4

3.人工智能 A.I. 应用技术 Not 算法和机器学习

4.webSocket 全双工通讯 IM即时通讯

5.Mui(布局,布局一个 ) + HTML5Plus(打开硬件有封装) App (工作了,就是一个小儿科,这些框架,质的飞跃)

6.智能玩具 + 机器学习

0 Django 和 Flask 优劣势

Django 15天

​ 优势:组件全 - admin - Model ORM - Forms
​ 教科书式(其他框架和他像)

​ 劣势:加载的组件是全部的组件 - 占用资源较高
​ 重型框架

Flask 3 天

​ 优势:轻如鸿毛 扩展性极强 三方组件全

​ 劣势:什么组件都没有
​ 三方组件全 - 版本兼容问题 导致不稳定
​ 线程的支持(不如dj)

1 flask 初识

1.1 flask 安装+启动

安装

新建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 可以连接,但是没有返回视图

1.2 模板的书写

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

1.3 flask1.1之前使用jsonify

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)

2 send_file 发送文件

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')

if name == 'main':

作用:执行的时候才走,被别的调用的时候不走了

from flask import Flask,render_template
app = Flask(__name__)

@app.route('/login')
def login():
    return render_template('login.html')

if __name__ == '__main__':  # 只有调用的时候才执行  别的文件引入时候不执行
    app.run()

2 . request

<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
2.2 request参数
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覆盖
2. #指定目录保存

默认保存到主目录(项目)下

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 
2.# 自动重启

django自带的

# app.config['DEBUG'] = True
app.debug = True #避免重启

按ctrl + s  重启 
切换也重启 
2.# url? 传参
<http://127.0.0.1:5000/login?id=1>

这样访问 ?传输参数 不会对地址路由造成影响 是传参了

3 模板传参的写法

3.1 py 视图
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)
3.2 模板文件写法
(1)stu_info
<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的慎用
(2)stu_list
{% for foo in stu_list %}	#(改性别)
   <td>{% if foo.gender!='男' and foo.gender!='女' %}
                女
                 {% else %}
                {{ foo.gender }}
(3)stu_dict(两种方式 dict或者items()(不要忘了括号))
{% 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 }}#}
(4)所有的模板都用到这个函数(传函数)
@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
(5)宏函数(什么用?)生成一个标签?
{% 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}}		#使用
3.2 jinja2

{{}} 引用 or 执行

{%%} 逻辑语法 if for else

今天上课都是因为一个,逗号困住,所以不得往下面的,可惜,细节

4 session

登录页面提交方式

<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"))			#基本一样
登录+加入session(默认31天)
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
session登录
@app.route('/detail')
def detail():
    if session.get('username'):
        return render_template('index.html')
    else:
        return redirect('/login')

session存到哪了?

Flask中的Session 不是三方组件 //Flask-Session

  1. 内置的

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,会暴露密钥,在前端页面显示错误的时候,可能就会暴露,相对安全不是绝对的安全了

5 全局变量global

错了好多次了

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个)

遇到特别不屑的,直接走,转身走(不要回头)

sanic

学习稍微难些
最新的框架,python最快的 (先天写的东西都比他快的很多)(世界上没有最好的语言,自己用的就是最好的,没有最好的程序员,自己) python数据计算非常快

错误1 多加了个逗号字典变元祖

STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'} ,

stu_info = STUDENT 时 , stu_info.name 等都没有值,是空的 ,而stu_info 有值 等于:
({'name': 'Old', 'age': 38, 'gender': '中'},)

以后不要犯这种错误

多加了个,成了元祖类型了(其实提示了tuple not get ,但是不看提示,看了也不懂把)

自己写程序出的错

错误2 AttributeError

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"])#直接写上面

错误3 记错命令 还一直坚持尝试

ctrl + enter 不是快速导入的命令
alt + enter 才是快速导入模块的命令

快捷键1

再加个命令 ctrl+shift+i 是前端的检查快捷键

原文地址:https://www.cnblogs.com/Doner/p/11163116.html