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 是前端的檢查快捷鍵